Skip to content

Commit ed06ab8

Browse files
[CXX-2625] More type traits + invoke() (#1042)
* Bring additional type_traits This implements additional types traits from C++14 and beyond. These are not part of the public API but can be used internally. * Bring along an `invoke()`
1 parent 4b08bcb commit ed06ab8

File tree

15 files changed

+696
-94
lines changed

15 files changed

+696
-94
lines changed

src/bsoncxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ set_dist_list(src_bsoncxx_include_DIST
5959
bsoncxx/v_noabi/bsoncxx/stdx/make_unique.hpp
6060
bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp
6161
bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp
62+
bsoncxx/v_noabi/bsoncxx/stdx/type_traits.hpp
6263
bsoncxx/v_noabi/bsoncxx/string/to_string.hpp
6364
bsoncxx/v_noabi/bsoncxx/string/view_or_value.hpp
6465
bsoncxx/v_noabi/bsoncxx/types.hpp

src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/builder/basic/impl.hpp

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#include <bsoncxx/builder/basic/sub_array.hpp>
1818
#include <bsoncxx/builder/basic/sub_document.hpp>
19-
#include <bsoncxx/util/functor.hpp>
19+
#include <bsoncxx/stdx/type_traits.hpp>
2020

2121
#include <bsoncxx/config/prelude.hpp>
2222

@@ -27,31 +27,26 @@ namespace basic {
2727
namespace impl {
2828

2929
template <typename T>
30-
using takes_document = typename util::is_functor<T, void(sub_document)>;
31-
32-
template <typename T>
33-
using takes_array = typename util::is_functor<T, void(sub_array)>;
34-
35-
template <typename T>
36-
BSONCXX_INLINE typename std::enable_if<takes_document<T>::value, void>::type generic_append(
37-
core* core, T&& func) {
30+
BSONCXX_INLINE detail::requires_t<void, detail::is_invocable<T, sub_document>> //
31+
generic_append(core* core, T&& func) {
3832
core->open_document();
39-
func(sub_document(core));
33+
detail::invoke(std::forward<T>(func), sub_document(core));
4034
core->close_document();
4135
}
4236

43-
template <typename T>
44-
BSONCXX_INLINE typename std::enable_if<takes_array<T>::value, void>::type generic_append(core* core,
45-
T&& func) {
37+
template <typename T, typename Placeholder = void> // placeholder 'void' for VS2015 compat
38+
BSONCXX_INLINE detail::requires_t<void, detail::is_invocable<T, sub_array>> //
39+
generic_append(core* core, T&& func) {
4640
core->open_array();
47-
func(sub_array(core));
41+
detail::invoke(std::forward<T>(func), sub_array(core));
4842
core->close_array();
4943
}
5044

51-
template <typename T>
52-
BSONCXX_INLINE
53-
typename std::enable_if<!takes_document<T>::value && !takes_array<T>::value, void>::type
54-
generic_append(core* core, T&& t) {
45+
template <typename T, typename = void, typename = void>
46+
BSONCXX_INLINE detail::requires_not_t<void, //
47+
detail::is_invocable<T, sub_document>,
48+
detail::is_invocable<T, sub_array>>
49+
generic_append(core* core, T&& t) {
5550
core->append(std::forward<T>(t));
5651
}
5752

src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/builder/basic/sub_document.hpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <bsoncxx/builder/concatenate.hpp>
1919
#include <bsoncxx/builder/core.hpp>
2020
#include <bsoncxx/stdx/string_view.hpp>
21+
#include <bsoncxx/stdx/type_traits.hpp>
2122

2223
#include <bsoncxx/config/prelude.hpp>
2324

@@ -59,8 +60,7 @@ class sub_document {
5960
// Appends a basic::kvp where the key is a non-owning string view.
6061
//
6162
template <typename K, typename V>
62-
BSONCXX_INLINE typename std::enable_if<
63-
std::is_same<typename std::decay<K>::type, stdx::string_view>::value>::type
63+
BSONCXX_INLINE detail::requires_t<void, detail::is_alike<K, stdx::string_view>> //
6464
append_(std::tuple<K, V>&& t) {
6565
_core->key_view(std::forward<K>(std::get<0>(t)));
6666
impl::value_append(_core, std::forward<V>(std::get<1>(t)));
@@ -70,8 +70,7 @@ class sub_document {
7070
// Appends a basic::kvp where the key is an owning STL string.
7171
//
7272
template <typename K, typename V>
73-
BSONCXX_INLINE typename std::enable_if<
74-
std::is_same<typename std::decay<K>::type, std::string>::value>::type
73+
BSONCXX_INLINE detail::requires_t<void, detail::is_alike<K, std::string>> //
7574
append_(std::tuple<K, V>&& t) {
7675
_core->key_owned(std::forward<K>(std::get<0>(t)));
7776
impl::value_append(_core, std::forward<V>(std::get<1>(t)));

src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/builder/core.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <stdexcept>
1919
#include <type_traits>
2020

21+
#include "bsoncxx/stdx/type_traits.hpp"
2122
#include <bsoncxx/array/value.hpp>
2223
#include <bsoncxx/array/view.hpp>
2324
#include <bsoncxx/document/value.hpp>
@@ -508,7 +509,7 @@ class BSONCXX_API core {
508509
///
509510
template <typename T>
510511
BSONCXX_INLINE core& append(T* v) {
511-
static_assert(std::is_same<typename std::remove_const<T>::type, char>::value,
512+
static_assert(detail::is_alike<T, char>::value,
512513
"append is disabled for non-char pointer types");
513514
append(types::b_string{v});
514515

src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/builder/stream/array_context.hpp

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include <bsoncxx/builder/core.hpp>
2020
#include <bsoncxx/builder/stream/closed_context.hpp>
2121
#include <bsoncxx/builder/stream/helpers.hpp>
22-
#include <bsoncxx/util/functor.hpp>
22+
#include <bsoncxx/stdx/type_traits.hpp>
2323

2424
#include <bsoncxx/config/prelude.hpp>
2525

@@ -67,11 +67,10 @@ class array_context {
6767
/// The value to append
6868
///
6969
template <class T>
70-
BSONCXX_INLINE typename std::enable_if<
71-
!(util::is_functor<T, void(array_context<>)>::value ||
72-
util::is_functor<T, void(single_context)>::value ||
73-
std::is_same<typename std::remove_reference<T>::type, const finalize_type>::value),
74-
array_context>::type&
70+
BSONCXX_INLINE detail::requires_not_t<array_context&,
71+
detail::is_invocable<T, array_context<>>,
72+
detail::is_invocable<T, single_context>,
73+
detail::is_alike<T, finalize_type>>
7574
operator<<(T&& t) {
7675
_core->append(std::forward<T>(t));
7776
return *this;
@@ -86,11 +85,12 @@ class array_context {
8685
/// The callback to invoke
8786
///
8887
template <typename Func>
89-
BSONCXX_INLINE typename std::enable_if<(util::is_functor<Func, void(array_context<>)>::value ||
90-
util::is_functor<Func, void(single_context)>::value),
91-
array_context>::type&
92-
operator<<(Func&& func) {
93-
func(*this);
88+
BSONCXX_INLINE
89+
detail::requires_t<array_context&,
90+
detail::disjunction<detail::is_invocable<Func, array_context>,
91+
detail::is_invocable<Func, single_context>>>
92+
operator<<(Func&& func) {
93+
detail::invoke(std::forward<Func>(func), *this);
9494
return *this;
9595
}
9696

@@ -105,12 +105,10 @@ class array_context {
105105
/// @return A value type which holds the complete bson document.
106106
///
107107
template <typename T>
108-
BSONCXX_INLINE typename std::enable_if<
109-
std::is_same<base, closed_context>::value &&
110-
std::is_same<typename std::remove_reference<T>::type, const finalize_type>::value,
111-
// TODO(MSVC): This should just be 'array::value', but
112-
// VS2015U1 can't resolve the name.
113-
bsoncxx::array::value>::type
108+
BSONCXX_INLINE detail::requires_t<bsoncxx::array::value,
109+
std::is_same<base, closed_context>,
110+
detail::is_alike<T, finalize_type>>
111+
// VS2015U1 can't resolve the name.
114112
operator<<(T&&) {
115113
return _core->extract_array();
116114
}

src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/builder/stream/key_context.hpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include <bsoncxx/builder/stream/closed_context.hpp>
2020
#include <bsoncxx/builder/stream/value_context.hpp>
2121
#include <bsoncxx/stdx/string_view.hpp>
22-
#include <bsoncxx/util/functor.hpp>
22+
#include <bsoncxx/stdx/type_traits.hpp>
2323

2424
#include <bsoncxx/config/prelude.hpp>
2525

@@ -108,10 +108,9 @@ class key_context {
108108
/// The callback to invoke
109109
///
110110
template <typename T>
111-
BSONCXX_INLINE
112-
typename std::enable_if<util::is_functor<T, void(key_context<>)>::value, key_context>::type&
113-
operator<<(T&& func) {
114-
func(*this);
111+
BSONCXX_INLINE detail::requires_t<key_context&, detail::is_invocable<T, key_context>> //
112+
operator<<(T&& func) {
113+
detail::invoke(std::forward<T>(func), *this);
115114
return *this;
116115
}
117116

@@ -126,12 +125,9 @@ class key_context {
126125
/// @return A value type which holds the complete bson document.
127126
///
128127
template <typename T>
129-
BSONCXX_INLINE typename std::enable_if<
130-
std::is_same<base, closed_context>::value &&
131-
std::is_same<typename std::remove_reference<T>::type, const finalize_type>::value,
132-
// TODO(MSVC): This should just be 'document::value', but
133-
// VS2015U1 can't resolve the name.
134-
bsoncxx::document::value>::type
128+
BSONCXX_INLINE detail::requires_t<bsoncxx::document::value,
129+
std::is_same<base, closed_context>,
130+
detail::is_alike<T, finalize_type>>
135131
operator<<(T&&) {
136132
return _core->extract_document();
137133
}

src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/builder/stream/value_context.hpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <bsoncxx/builder/stream/array_context.hpp>
1919
#include <bsoncxx/builder/stream/closed_context.hpp>
2020
#include <bsoncxx/builder/stream/helpers.hpp>
21-
#include <bsoncxx/util/functor.hpp>
21+
#include <bsoncxx/stdx/type_traits.hpp>
2222

2323
#include <bsoncxx/config/prelude.hpp>
2424

@@ -63,9 +63,8 @@ class value_context {
6363
/// The value to append
6464
///
6565
template <class T>
66-
BSONCXX_INLINE
67-
typename std::enable_if<!util::is_functor<T, void(single_context)>::value, base>::type
68-
operator<<(T&& t) {
66+
BSONCXX_INLINE detail::requires_not_t<base, detail::is_invocable<T, single_context>> //
67+
operator<<(T&& t) {
6968
_core->append(std::forward<T>(t));
7069
return unwrap();
7170
}
@@ -78,10 +77,9 @@ class value_context {
7877
/// The callback to invoke
7978
///
8079
template <typename T>
81-
BSONCXX_INLINE
82-
typename std::enable_if<util::is_functor<T, void(single_context)>::value, base>::type
83-
operator<<(T&& func) {
84-
func(*this);
80+
BSONCXX_INLINE detail::requires_t<base, detail::is_invocable<T, single_context>> //
81+
operator<<(T&& func) {
82+
detail::invoke(std::forward<T>(func), *this);
8583
return unwrap();
8684
}
8785

src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/document/value.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
#include <cstdlib>
1818
#include <memory>
19+
#include <type_traits>
1920

21+
#include "bsoncxx/stdx/type_traits.hpp"
2022
#include <bsoncxx/array/view.hpp>
2123
#include <bsoncxx/document/view.hpp>
2224

@@ -84,8 +86,7 @@ class BSONCXX_API value {
8486
/// @param t
8587
/// A user-defined object to serialize into a BSON object.
8688
///
87-
template <typename T,
88-
typename std::enable_if<!std::is_same<T, typename array::view>::value, int>::type = 0>
89+
template <typename T, detail::requires_not_t<int, std::is_same<T, array::view>> = 0>
8990
explicit value(const T& t) : value({}) {
9091
to_bson(t, *this);
9192
}

src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/make_unique.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <type_traits>
2020
#include <utility>
2121

22+
#include "./type_traits.hpp"
23+
2224
#include <bsoncxx/config/prelude.hpp>
2325

2426
namespace bsoncxx {

0 commit comments

Comments
 (0)