blob: 3a25c58ef94410ee5bb3ce03bc2097804112cc3c [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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070035#elif defined(NDNBOOST_MSVC)
Jeff Thompsona28eed82013-08-22 16:21:10 -070036# 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.
Jeff Thompson3d613fd2013-10-15 15:39:04 -070044namespace NDNBOOST_JOIN(NDNBOOST_TT_TRAIT_NAME,_impl) {
Jeff Thompsona28eed82013-08-22 16:21:10 -070045
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070053// a type returned from operator NDNBOOST_TT_TRAIT_OP when no such operator is
Jeff Thompsona28eed82013-08-22 16:21:10 -070054// 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070063// when operator NDNBOOST_TT_TRAIT_OP is not available, this one is used
64no_operator operator NDNBOOST_TT_TRAIT_OP (const any&);
Jeff Thompsona28eed82013-08-22 16:21:10 -070065
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070071// operator NDNBOOST_TT_TRAIT_OP returns void and we can use the return type of
72// (NDNBOOST_TT_TRAIT_OP rhs, returns_void_t()) to deduce if
73// operator NDNBOOST_TT_TRAIT_OP returns void or not:
74// - operator NDNBOOST_TT_TRAIT_OP returns void -> (NDNBOOST_TT_TRAIT_OP rhs, returns_void_t()) returns returns_void_t
75// - operator NDNBOOST_TT_TRAIT_OP returns !=void -> (NDNBOOST_TT_TRAIT_OP rhs, returns_void_t()) returns int
Jeff Thompsona28eed82013-08-22 16:21:10 -070076struct 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:
Jeff Thompson3d613fd2013-10-15 15:39:04 -070081// - value==true -> operator NDNBOOST_TT_TRAIT_OP returns void
82// - value==false -> operator NDNBOOST_TT_TRAIT_OP does not return void
Jeff Thompsona28eed82013-08-22 16:21:10 -070083template < 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);
Jeff Thompson3d613fd2013-10-15 15:39:04 -070089 NDNBOOST_STATIC_CONSTANT(bool, value = (sizeof(::ndnboost::type_traits::yes_type)==sizeof(returns_void((NDNBOOST_TT_TRAIT_OP make<Rhs>(),returns_void_t())))));
Jeff Thompsona28eed82013-08-22 16:21:10 -070090};
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 > {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700103 NDNBOOST_STATIC_CONSTANT(bool, value = true);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700104};
105
106template < typename Rhs >
107struct operator_returns_Ret < Rhs, dont_care, false > {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700108 NDNBOOST_STATIC_CONSTANT(bool, value = true);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700109};
110
111template < typename Rhs >
112struct operator_returns_Ret < Rhs, void, true > {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700113 NDNBOOST_STATIC_CONSTANT(bool, value = true);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700114};
115
116template < typename Rhs >
117struct operator_returns_Ret < Rhs, void, false > {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700118 NDNBOOST_STATIC_CONSTANT(bool, value = false);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700119};
120
121template < typename Rhs, typename Ret >
122struct operator_returns_Ret < Rhs, Ret, true > {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700123 NDNBOOST_STATIC_CONSTANT(bool, value = false);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700124};
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700134 NDNBOOST_STATIC_CONSTANT(bool, value = (sizeof(is_convertible_to_Ret(NDNBOOST_TT_TRAIT_OP make<Rhs>()))==sizeof(::ndnboost::type_traits::yes_type)));
Jeff Thompsona28eed82013-08-22 16:21:10 -0700135};
136
137
138// 5. checks for operator existence
139// condition: Rhs!=void
140
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700141// checks if our definition of operator NDNBOOST_TT_TRAIT_OP is used or an other
Jeff Thompsona28eed82013-08-22 16:21:10 -0700142// 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700152 NDNBOOST_STATIC_CONSTANT(bool, value = (sizeof(check(((NDNBOOST_TT_TRAIT_OP make<Rhs>()),make<has_operator>())))==sizeof(::ndnboost::type_traits::yes_type)));
Jeff Thompsona28eed82013-08-22 16:21:10 -0700153};
154
155
156// 6. main trait: to avoid any compilation error, this class behaves
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700157// differently when operator NDNBOOST_TT_TRAIT_OP(Rhs) is forbidden by the
Jeff Thompsona28eed82013-08-22 16:21:10 -0700158// standard.
159// Forbidden_if is a bool that is:
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700160// - true when the operator NDNBOOST_TT_TRAIT_OP(Rhs) is forbidden by the standard
Jeff Thompsona28eed82013-08-22 16:21:10 -0700161// (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 > {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700168 NDNBOOST_STATIC_CONSTANT(bool, value = false);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700169};
170
171template < typename Rhs, typename Ret >
172struct trait_impl1 < Rhs, Ret, false > {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700173 NDNBOOST_STATIC_CONSTANT(bool,
Jeff Thompsona28eed82013-08-22 16:21:10 -0700174 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 > {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700186 NDNBOOST_STATIC_CONSTANT(bool, value = false);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700187};
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;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700195 NDNBOOST_STATIC_CONSTANT(bool, value = (trait_impl1 < Rhs_noref, Ret, NDNBOOST_TT_FORBIDDEN_IF >::value));
Jeff Thompsona28eed82013-08-22 16:21:10 -0700196};
197
198} // namespace impl
199} // namespace detail
200
201// this is the accessible definition of the trait to end user
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700202NDNBOOST_TT_AUX_BOOL_TRAIT_DEF2(NDNBOOST_TT_TRAIT_NAME, Rhs, Ret=::ndnboost::detail::NDNBOOST_JOIN(NDNBOOST_TT_TRAIT_NAME,_impl)::dont_care, (::ndnboost::detail::NDNBOOST_JOIN(NDNBOOST_TT_TRAIT_NAME,_impl)::trait_impl < Rhs, Ret >::value))
Jeff Thompsona28eed82013-08-22 16:21:10 -0700203
204} // namespace ndnboost
205
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700206#if defined(NDNBOOST_MSVC)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700207# pragma warning ( pop )
208#endif
209
210#include <ndnboost/type_traits/detail/bool_trait_undef.hpp>