MongoDB C++ Driver mongocxx-3.0.3
Loading...
Searching...
No Matches
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
21namespace bsoncxx {
22BSONCXX_INLINE_NAMESPACE_BEGIN
23namespace 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
32template <typename FunctionLike, typename Signature>
33using is_functor = std::is_convertible<FunctionLike, std::function<Signature>>;
34
35#else
36
37namespace functor {
38
39template <typename, typename>
40struct build_free_function;
41
42template <typename F, typename R, typename... Args>
43struct build_free_function<F, R(Args...)> {
44 typedef R (*type)(Args...);
45};
46
47template <typename, typename>
48struct build_class_function;
49
50template <typename C, typename R, typename... Args>
51struct build_class_function<C, R(Args...)> {
52 typedef R (C::*type)(Args...);
53};
54
55template <typename>
56struct strip_cv_from_class_function;
57
58template <typename C, typename R, typename... Args>
59struct strip_cv_from_class_function<R (C::*)(Args...)> {
60 typedef R (C::*type)(Args...);
61};
62
63template <typename C, typename R, typename... Args>
64struct strip_cv_from_class_function<R (C::*)(Args...) const> {
65 typedef R (C::*type)(Args...);
66};
67
68template <typename C, typename R, typename... Args>
69struct strip_cv_from_class_function<R (C::*)(Args...) volatile> {
70 typedef R (C::*type)(Args...);
71};
72
73template <typename C, typename S>
74struct 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
92template <typename F, typename S>
93struct is_function_with_signature
94 : std::is_convertible<F, typename build_free_function<F, S>::type> {};
95
96template <typename C, typename S, bool>
97struct is_functor_impl : is_class_method_with_signature<C, S> {};
98
99template <typename F, typename S>
100struct is_functor_impl<F, S, false> : is_function_with_signature<F, S> {};
101
102} // namespace functor
103
104template <typename C, typename S>
105struct is_functor : functor::is_functor_impl<C, S, std::is_class<C>::value> {};
106
107#endif
108
109} // namespace util
110BSONCXX_INLINE_NAMESPACE_END
111} // namespace bsoncxx
112
113#include <bsoncxx/config/postlude.hpp>