]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* Copyright 2017 Joaquin M Lopez Munoz. |
2 | * Distributed under the Boost Software License, Version 1.0. | |
3 | * (See accompanying file LICENSE_1_0.txt or copy at | |
4 | * http://www.boost.org/LICENSE_1_0.txt) | |
5 | * | |
6 | * See http://www.boost.org/libs/poly_collection for library home page. | |
7 | */ | |
8 | ||
9 | #ifndef BOOST_TT_DETAIL_IS_LIKELY_STATELESS_LAMBDA_HPP | |
10 | #define BOOST_TT_DETAIL_IS_LIKELY_STATELESS_LAMBDA_HPP | |
11 | ||
12 | #if defined(_MSC_VER) | |
13 | #pragma once | |
14 | #endif | |
15 | ||
16 | #include <boost/type_traits/detail/config.hpp> | |
17 | #include <boost/type_traits/integral_constant.hpp> | |
18 | ||
19 | #if defined(BOOST_TT_HAS_ACCURATE_BINARY_OPERATOR_DETECTION) | |
20 | // | |
21 | // We don't need or use this, just define a dummy class: | |
22 | // | |
23 | namespace boost{ namespace type_traits_detail{ | |
24 | ||
25 | template<typename T> | |
26 | struct is_likely_stateless_lambda : public false_type {}; | |
27 | ||
28 | }} | |
29 | ||
92f5a8d4 TL |
30 | #elif !defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !BOOST_WORKAROUND(BOOST_MSVC, < 1900)\ |
31 | && !(BOOST_WORKAROUND(BOOST_MSVC, == 1900) && defined(__CLR_VER)) | |
11fdf7f2 TL |
32 | |
33 | #include <boost/type_traits/is_convertible.hpp> | |
92f5a8d4 | 34 | #include <boost/type_traits/enable_if.hpp> |
11fdf7f2 TL |
35 | |
36 | namespace boost{ | |
37 | ||
38 | namespace type_traits_detail{ | |
39 | ||
40 | /* Stateless lambda expressions have one (and only one) call operator and are | |
41 | * convertible to a function pointer with the same signature. Non-lambda types | |
42 | * could satisfy this too, hence the "likely" qualifier. | |
43 | */ | |
44 | ||
45 | template<typename T> | |
46 | struct has_one_operator_call_helper | |
47 | { | |
48 | template<typename Q> static boost::true_type test(decltype(&Q::operator())*); | |
49 | template<typename> static boost::false_type test(...); | |
50 | ||
51 | using type=decltype(test<T>(nullptr)); | |
52 | }; | |
53 | ||
54 | template<typename T> | |
55 | using has_one_operator_call=typename has_one_operator_call_helper<T>::type; | |
56 | ||
57 | template<typename T> | |
58 | struct equivalent_function_pointer | |
59 | { | |
60 | template<typename Q,typename R,typename... Args> | |
61 | static auto helper(R (Q::*)(Args...)const)->R(*)(Args...); | |
62 | template<typename Q,typename R,typename... Args> | |
63 | static auto helper(R (Q::*)(Args...))->R(*)(Args...); | |
64 | ||
65 | using type=decltype(helper(&T::operator())); | |
66 | }; | |
67 | ||
68 | template<typename T,typename=void> | |
69 | struct is_likely_stateless_lambda : false_type{}; | |
70 | ||
71 | template<typename T> | |
72 | struct is_likely_stateless_lambda< | |
73 | T, | |
92f5a8d4 | 74 | typename boost::enable_if_<has_one_operator_call<T>::value>::type> : |
11fdf7f2 TL |
75 | boost::is_convertible<T, typename equivalent_function_pointer<T>::type |
76 | >{}; | |
77 | ||
78 | } /* namespace type_traits_detail */ | |
79 | ||
80 | } /* namespace boost */ | |
81 | ||
82 | #else | |
83 | // | |
84 | // Can't implement this: | |
85 | // | |
86 | namespace boost { | |
87 | namespace type_traits_detail { | |
88 | ||
89 | template<typename T> | |
90 | struct is_likely_stateless_lambda : public boost::integral_constant<bool, false> {}; | |
91 | }} | |
92 | ||
93 | #endif | |
94 | #endif | |
95 |