MongoDB C++ Driver  mongocxx-3.0.1
functor.hpp
1 // Copyright 2014 MongoDB Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <type_traits>
18 
19 #include <bsoncxx/config/prelude.hpp>
20 
21 namespace bsoncxx {
22 BSONCXX_INLINE_NAMESPACE_BEGIN
23 namespace util {
24 
25 // TODO(MSVC): VS2015U1 Completely falls apart trying to honor the
26 // simple definition of is_functor since is_convertible returns the
27 // wrong results for std::function, so we fall back to a bunch of
28 // other template metaprogramming there.
29 
30 #if !defined(_MSC_VER)
31 
32 template <typename FunctionLike, typename Signature>
33 using is_functor = std::is_convertible<FunctionLike, std::function<Signature>>;
34 
35 #else
36 
37 namespace functor {
38 
39 template <typename, typename>
40 struct build_free_function;
41 
42 template <typename F, typename R, typename... Args>
43 struct build_free_function<F, R(Args...)> {
44  typedef R (*type)(Args...);
45 };
46 
47 template <typename, typename>
48 struct build_class_function;
49 
50 template <typename C, typename R, typename... Args>
51 struct build_class_function<C, R(Args...)> {
52  typedef R (C::*type)(Args...);
53 };
54 
55 template <typename>
56 struct strip_cv_from_class_function;
57 
58 template <typename C, typename R, typename... Args>
59 struct strip_cv_from_class_function<R (C::*)(Args...)> {
60  typedef R (C::*type)(Args...);
61 };
62 
63 template <typename C, typename R, typename... Args>
64 struct strip_cv_from_class_function<R (C::*)(Args...) const> {
65  typedef R (C::*type)(Args...);
66 };
67 
68 template <typename C, typename R, typename... Args>
69 struct strip_cv_from_class_function<R (C::*)(Args...) volatile> {
70  typedef R (C::*type)(Args...);
71 };
72 
73 template <typename C, typename S>
74 struct is_class_method_with_signature {
75  typedef int yes;
76  typedef char no;
77 
78  // T stands for SFINAE
79  template <typename T>
80  static typename std::enable_if<std::is_convertible<typename build_class_function<C, S>::type,
81  typename strip_cv_from_class_function<
82  decltype(&T::operator())>::type>::value,
83  yes>::type
84  sfinae(void *);
85 
86  template <typename>
87  static no sfinae(...);
88 
89  static bool constexpr value = sizeof(sfinae<C>(nullptr)) == sizeof(yes);
90 };
91 
92 template <typename F, typename S>
93 struct is_function_with_signature
94  : std::is_convertible<F, typename build_free_function<F, S>::type> {};
95 
96 template <typename C, typename S, bool>
97 struct is_functor_impl : is_class_method_with_signature<C, S> {};
98 
99 template <typename F, typename S>
100 struct is_functor_impl<F, S, false> : is_function_with_signature<F, S> {};
101 
102 } // namespace functor
103 
104 template <typename C, typename S>
105 struct is_functor : functor::is_functor_impl<C, S, std::is_class<C>::value> {};
106 
107 #endif
108 
109 } // namespace util
110 BSONCXX_INLINE_NAMESPACE_END
111 } // namespace bsoncxx
112 
113 #include <bsoncxx/config/postlude.hpp>
Definition: element.hpp:24