1 // Copyright 2015 The Android Open Source Project
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <type_traits>
25 // a simple helper class for SFINAE below.
26 template <class X = void>
31 } // namespaces details
33 // add some convenience shortcuts for an overly complex std::enable_if syntax
35 // Use 'enable_if<Predicate,Type>' instead of
36 // 'typename std::enable_if<Predicate::value,Type>::type'
37 template <class Predicate, class Type = void*>
38 using enable_if = typename std::enable_if<Predicate::value, Type>::type;
40 // Use 'enable_if_c<BooleanFlag,Type>' instead of
41 // 'typename std::enable_if<BooleanFlag,Type>::type'
42 template <bool predicate, class Type = void*>
43 using enable_if_c = typename std::enable_if<predicate, Type>::type;
45 // Use 'enable_if_convertible<From,To,Type>' instead of
46 // 'typename std::enable_if<std::is_convertible<From,To>::value, Type>::type'
47 template <class From, class To, class Type = void*>
48 using enable_if_convertible = enable_if<std::is_convertible<From, To>>;
50 // -----------------------------------------------------------------------------
51 // A predicate for checking if some object is callable with a specific
52 // signature. Examples:
54 // is_callable_as<int, void()>::value == false.
55 // is_callable_as<strcmp, void()>::value == false.
56 // is_callable_as<strcmp, int(const char*, const char*)>::value == true
58 template <class F, class Signature, class X = void>
59 struct is_callable_as : std::false_type {};
61 // This specialization is SFINAE-d out if template arguments can't be combined
62 // into a call expression F(), or if the result of that call is not |R|
63 template <class F, class R>
64 struct is_callable_as<
65 F, R(), typename std::enable_if<std::is_same<
66 typename details::dummy<decltype(std::declval<F>()())>::type,
67 R>::value>::type> : std::true_type {};
69 // One more specialization, for non empty argument list
70 template <class F, class R, class... Args>
71 struct is_callable_as<F, R(Args...),
72 typename std::enable_if<std::is_same<
73 typename details::dummy<decltype(std::declval<F>()(
74 std::declval<Args>()...))>::type,
75 R>::value>::type> : std::true_type {};
76 // -----------------------------------------------------------------------------
77 // Check if a type |T| is any instantiation of a template |U|. Examples:
79 // is_template_instantiation_of<int, std::vector>::value == false
80 // is_template_instantiation_of<
81 // std::list<std::vector<int>>, std::vector>::value == false
82 // is_template_instantiation_of<std::vector<int>, std::vector>::value == true
83 // is_template_instantiation_of<
84 // std::vector<std::vector<int>>, std::vector>::value == true
86 template <class T, template <class...> class U>
87 struct is_template_instantiation_of : std::false_type {};
89 template <template <class...> class U, class... Args>
90 struct is_template_instantiation_of<U<Args...>, U> : std::true_type {};
91 // -----------------------------------------------------------------------------
94 // is_range<T> - check if type |T| is a range-like type.
96 // It makes sure that expressions std::begin(t) and std::end(t) are well-formed
97 // and those return the same type.
99 // Note: with expression SFINAE from C++14 is_range_helper<> could be renamed to
100 // is_range<> with no extra code. C++11 needs an extra level of enable_if<>
101 // to make it work when the type isn't a range.
107 using is_range_helper = std::is_same<
109 std::declval<typename std::add_lvalue_reference<T>::type>())),
111 std::end(std::declval<typename std::add_lvalue_reference<T>::type>()))>;
113 } // namespace details
115 template <class T, class = void>
116 struct is_range : std::false_type {};
120 T, typename std::enable_if<details::is_range_helper<T>::value>::type>
123 } // namespace common