blob: b1113d2e9c75b986bda07deda8c6dd988ad70721 [file] [log] [blame]
Jeff Thompsona28eed82013-08-22 16:21:10 -07001// (C) Copyright 2009-2011 Frederic Bron, Robert Stewart, Steven Watanabe & Roman Perepelitsa.
2//
3// Use, modification and distribution are subject to the Boost Software License,
4// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt).
6//
7// See http://www.boost.org/libs/type_traits for most recent version including documentation.
8
9#include <ndnboost/config.hpp>
10#include <ndnboost/type_traits/ice.hpp>
11#include <ndnboost/type_traits/integral_constant.hpp>
12#include <ndnboost/type_traits/is_const.hpp>
13#include <ndnboost/type_traits/is_fundamental.hpp>
14#include <ndnboost/type_traits/is_integral.hpp>
15#include <ndnboost/type_traits/is_pointer.hpp>
16#include <ndnboost/type_traits/is_same.hpp>
17#include <ndnboost/type_traits/is_void.hpp>
18#include <ndnboost/type_traits/remove_cv.hpp>
19#include <ndnboost/type_traits/remove_pointer.hpp>
20#include <ndnboost/type_traits/remove_reference.hpp>
21
22// should be the last #include
23#include <ndnboost/type_traits/detail/bool_trait_def.hpp>
24
25// cannot include this header without getting warnings of the kind:
26// gcc:
27// warning: value computed is not used
28// warning: comparison between signed and unsigned integer expressions
29// msvc:
30// warning C4146: unary minus operator applied to unsigned type, result still unsigned
31// warning C4804: '-' : unsafe use of type 'bool' in operation
32// cannot find another implementation -> declared as system header to suppress these warnings.
33#if defined(__GNUC__) && ((__GNUC__==3 && __GNUC_MINOR__>=1) || (__GNUC__>3))
34# pragma GCC system_header
35#elif defined(BOOST_MSVC)
36# pragma warning ( push )
37# pragma warning ( disable : 4146 4804 4913 4244 )
38#endif
39
40namespace ndnboost {
41namespace detail {
42
43// This namespace ensures that argument-dependent name lookup does not mess things up.
44namespace BOOST_JOIN(BOOST_TT_TRAIT_NAME,_impl) {
45
46// 1. a function to have an instance of type T without requiring T to be default
47// constructible
48template <typename T> T &make();
49
50
51// 2. we provide our operator definition for types that do not have one already
52
53// a type returned from operator BOOST_TT_TRAIT_OP when no such operator is
54// found in the type's own namespace (our own operator is used) so that we have
55// a means to know that our operator was used
56struct no_operator { };
57
58// this class allows implicit conversions and makes the following operator
59// definition less-preferred than any other such operators that might be found
60// via argument-dependent name lookup
61struct any { template <class T> any(T const&); };
62
63// when operator BOOST_TT_TRAIT_OP is not available, this one is used
64no_operator operator BOOST_TT_TRAIT_OP (const any&);
65
66
67// 3. checks if the operator returns void or not
68// conditions: Rhs!=void
69
70// we first redefine "operator," so that we have no compilation error if
71// operator BOOST_TT_TRAIT_OP returns void and we can use the return type of
72// (BOOST_TT_TRAIT_OP rhs, returns_void_t()) to deduce if
73// operator BOOST_TT_TRAIT_OP returns void or not:
74// - operator BOOST_TT_TRAIT_OP returns void -> (BOOST_TT_TRAIT_OP rhs, returns_void_t()) returns returns_void_t
75// - operator BOOST_TT_TRAIT_OP returns !=void -> (BOOST_TT_TRAIT_OP rhs, returns_void_t()) returns int
76struct returns_void_t { };
77template <typename T> int operator,(const T&, returns_void_t);
78template <typename T> int operator,(const volatile T&, returns_void_t);
79
80// this intermediate trait has member value of type bool:
81// - value==true -> operator BOOST_TT_TRAIT_OP returns void
82// - value==false -> operator BOOST_TT_TRAIT_OP does not return void
83template < typename Rhs >
84struct operator_returns_void {
85 // overloads of function returns_void make the difference
86 // yes_type and no_type have different size by construction
87 static ::ndnboost::type_traits::yes_type returns_void(returns_void_t);
88 static ::ndnboost::type_traits::no_type returns_void(int);
89 BOOST_STATIC_CONSTANT(bool, value = (sizeof(::ndnboost::type_traits::yes_type)==sizeof(returns_void((BOOST_TT_TRAIT_OP make<Rhs>(),returns_void_t())))));
90};
91
92
93// 4. checks if the return type is Ret or Ret==dont_care
94// conditions: Rhs!=void
95
96struct dont_care { };
97
98template < typename Rhs, typename Ret, bool Returns_void >
99struct operator_returns_Ret;
100
101template < typename Rhs >
102struct operator_returns_Ret < Rhs, dont_care, true > {
103 BOOST_STATIC_CONSTANT(bool, value = true);
104};
105
106template < typename Rhs >
107struct operator_returns_Ret < Rhs, dont_care, false > {
108 BOOST_STATIC_CONSTANT(bool, value = true);
109};
110
111template < typename Rhs >
112struct operator_returns_Ret < Rhs, void, true > {
113 BOOST_STATIC_CONSTANT(bool, value = true);
114};
115
116template < typename Rhs >
117struct operator_returns_Ret < Rhs, void, false > {
118 BOOST_STATIC_CONSTANT(bool, value = false);
119};
120
121template < typename Rhs, typename Ret >
122struct operator_returns_Ret < Rhs, Ret, true > {
123 BOOST_STATIC_CONSTANT(bool, value = false);
124};
125
126// otherwise checks if it is convertible to Ret using the sizeof trick
127// based on overload resolution
128// condition: Ret!=void and Ret!=dont_care and the operator does not return void
129template < typename Rhs, typename Ret >
130struct operator_returns_Ret < Rhs, Ret, false > {
131 static ::ndnboost::type_traits::yes_type is_convertible_to_Ret(Ret); // this version is preferred for types convertible to Ret
132 static ::ndnboost::type_traits::no_type is_convertible_to_Ret(...); // this version is used otherwise
133
134 BOOST_STATIC_CONSTANT(bool, value = (sizeof(is_convertible_to_Ret(BOOST_TT_TRAIT_OP make<Rhs>()))==sizeof(::ndnboost::type_traits::yes_type)));
135};
136
137
138// 5. checks for operator existence
139// condition: Rhs!=void
140
141// checks if our definition of operator BOOST_TT_TRAIT_OP is used or an other
142// existing one;
143// this is done with redefinition of "operator," that returns no_operator or has_operator
144struct has_operator { };
145no_operator operator,(no_operator, has_operator);
146
147template < typename Rhs >
148struct operator_exists {
149 static ::ndnboost::type_traits::yes_type check(has_operator); // this version is preferred when operator exists
150 static ::ndnboost::type_traits::no_type check(no_operator); // this version is used otherwise
151
152 BOOST_STATIC_CONSTANT(bool, value = (sizeof(check(((BOOST_TT_TRAIT_OP make<Rhs>()),make<has_operator>())))==sizeof(::ndnboost::type_traits::yes_type)));
153};
154
155
156// 6. main trait: to avoid any compilation error, this class behaves
157// differently when operator BOOST_TT_TRAIT_OP(Rhs) is forbidden by the
158// standard.
159// Forbidden_if is a bool that is:
160// - true when the operator BOOST_TT_TRAIT_OP(Rhs) is forbidden by the standard
161// (would yield compilation error if used)
162// - false otherwise
163template < typename Rhs, typename Ret, bool Forbidden_if >
164struct trait_impl1;
165
166template < typename Rhs, typename Ret >
167struct trait_impl1 < Rhs, Ret, true > {
168 BOOST_STATIC_CONSTANT(bool, value = false);
169};
170
171template < typename Rhs, typename Ret >
172struct trait_impl1 < Rhs, Ret, false > {
173 BOOST_STATIC_CONSTANT(bool,
174 value = (
175 ::ndnboost::type_traits::ice_and<
176 operator_exists < Rhs >::value,
177 operator_returns_Ret < Rhs, Ret, operator_returns_void < Rhs >::value >::value
178 >::value
179 )
180 );
181};
182
183// specialization needs to be declared for the special void case
184template < typename Ret >
185struct trait_impl1 < void, Ret, false > {
186 BOOST_STATIC_CONSTANT(bool, value = false);
187};
188
189// defines some typedef for convenience
190template < typename Rhs, typename Ret >
191struct trait_impl {
192 typedef typename ::ndnboost::remove_reference<Rhs>::type Rhs_noref;
193 typedef typename ::ndnboost::remove_cv<Rhs_noref>::type Rhs_nocv;
194 typedef typename ::ndnboost::remove_cv< typename ::ndnboost::remove_reference< typename ::ndnboost::remove_pointer<Rhs_noref>::type >::type >::type Rhs_noptr;
195 BOOST_STATIC_CONSTANT(bool, value = (trait_impl1 < Rhs_noref, Ret, BOOST_TT_FORBIDDEN_IF >::value));
196};
197
198} // namespace impl
199} // namespace detail
200
201// this is the accessible definition of the trait to end user
202BOOST_TT_AUX_BOOL_TRAIT_DEF2(BOOST_TT_TRAIT_NAME, Rhs, Ret=::ndnboost::detail::BOOST_JOIN(BOOST_TT_TRAIT_NAME,_impl)::dont_care, (::ndnboost::detail::BOOST_JOIN(BOOST_TT_TRAIT_NAME,_impl)::trait_impl < Rhs, Ret >::value))
203
204} // namespace ndnboost
205
206#if defined(BOOST_MSVC)
207# pragma warning ( pop )
208#endif
209
210#include <ndnboost/type_traits/detail/bool_trait_undef.hpp>