]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
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_POLY_COLLECTION_DETAIL_IS_LIKELY_STATELESS_LAMBDA_HPP | |
10 | #define BOOST_POLY_COLLECTION_DETAIL_IS_LIKELY_STATELESS_LAMBDA_HPP | |
11 | ||
12 | #if defined(_MSC_VER) | |
13 | #pragma once | |
14 | #endif | |
15 | ||
16 | #include <type_traits> | |
17 | ||
18 | namespace boost{ | |
19 | ||
20 | namespace poly_collection{ | |
21 | ||
22 | namespace detail{ | |
23 | ||
24 | /* Stateless lambda expressions have one (and only one) call operator and are | |
25 | * convertible to a function pointer with the same signature. Non-lambda types | |
26 | * could satisfy this too, hence the "likely" qualifier. | |
27 | */ | |
28 | ||
29 | template<typename T> | |
30 | struct has_one_operator_call_helper | |
31 | { | |
32 | template<typename Q> static std::true_type test(decltype(&Q::operator())*); | |
33 | template<typename> static std::false_type test(...); | |
34 | ||
35 | using type=decltype(test<T>(nullptr)); | |
36 | }; | |
37 | ||
38 | template<typename T> | |
39 | using has_one_operator_call=typename has_one_operator_call_helper<T>::type; | |
40 | ||
41 | template<typename T> | |
42 | struct equivalent_function_pointer | |
43 | { | |
44 | template<typename Q,typename R,typename... Args> | |
45 | static auto helper(R (Q::*)(Args...)const)->R(*)(Args...); | |
46 | template<typename Q,typename R,typename... Args> | |
47 | static auto helper(R (Q::*)(Args...))->R(*)(Args...); | |
48 | ||
49 | using type=decltype(helper(&T::operator())); | |
50 | }; | |
51 | ||
52 | template<typename T,typename=void> | |
53 | struct is_likely_stateless_lambda:std::false_type{}; | |
54 | ||
55 | template<typename T> | |
56 | struct is_likely_stateless_lambda< | |
57 | T, | |
58 | typename std::enable_if<has_one_operator_call<T>::value>::type | |
59 | >:std::is_convertible< | |
60 | T, | |
61 | typename equivalent_function_pointer<T>::type | |
62 | >{}; | |
63 | ||
64 | } /* namespace poly_collection::detail */ | |
65 | ||
66 | } /* namespace poly_collection */ | |
67 | ||
68 | } /* namespace boost */ | |
69 | ||
70 | #endif |