iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TypeTraitsHelpers.H
Go to the documentation of this file.
1 /*! @file
2  @author David J. Berg (dberg@usc.edu)
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
36 #ifndef INCLUDE_NRT_CORE_TYPING_DETAILS_TYPETRAITSHELPERS_H
37 #define INCLUDE_NRT_CORE_TYPING_DETAILS_TYPETRAITSHELPERS_H
38 
39 #include <type_traits>
40 
41 namespace nrt
42 {
43  //! A set of type trait class to check if two types can be used in an arithmetic operation, or compared
44  /*!
45  See nrt::nrt_traits on how to use the function_existence_helper. The namespace supports classes which can be
46  derived from to perform compile time checks for functions which take one or two arguments.
47  */
48  namespace function_existence_helper
49  {
50  // A type returned by the binary operator for any struct in this namespace
51  // where T does not support the operator.
52  struct no_support {};
53 
54  // These types soaks up any implicit conversions and makes the following
55  // binary operator less preferred than any other such operator found duirng
56  // the argument dependent lookup (ADL)
57  struct any_class1 { template <class T> any_class1(T const&); };//can convert any type
58  struct any_class2 { template <class T> any_class2(T const&); };//can convert any type
59 
60  // Fallback operators for when the binary operator for types T are not supported
61  // use a macro here to help us define them for a bunch of operators
62  no_support operator == (any_class1 const&, any_class2 const&);
63  no_support operator < (any_class1 const&, any_class2 const&);
64  no_support operator <= (any_class1 const&, any_class2 const&);
65  no_support operator > (any_class1 const&, any_class2 const&);
66  no_support operator >= (any_class1 const&, any_class2 const&);
67 
68  no_support operator + (any_class1 const&, any_class2 const&);
69  no_support operator - (any_class1 const&, any_class2 const&);
70  no_support operator * (any_class1 const&, any_class2 const&);
71  no_support operator / (any_class1 const&, any_class2 const&);
72  no_support operator += (any_class1 const&, any_class2 const&);
73  no_support operator -= (any_class1 const&, any_class2 const&);
74  no_support operator *= (any_class1 const&, any_class2 const&);
75  no_support operator /= (any_class1 const&, any_class2 const&);
76 
77  // Two typedefs overloads to distinguish whether T supports a certain operator
78  // expression. The first typedef is a reference to a two-element character
79  // array and is chosen if T does not support the expression. The second
80  // overload returns a char and is chosen if T supports the expression. So
81  // using sizeof(check(<expression>)) returns 2 for the first overload and 1
82  // for the second overload.
83  typedef char (&no)[2];
84  typedef char yes;
85 
86  no check(no_support);
87  template <class T> yes check(T const&);//this will be a bool most likely if an operator is found
88 
89  // Implementation for equality template metafunction.
90  template <class T ,class U>
91  struct is_equality_comparable_impl
92  {
93  static typename std::remove_cv<typename std::remove_reference<T>::type>::type const& x;
94  static typename std::remove_cv<typename std::remove_reference<U>::type>::type const& y;
95  static const bool value = sizeof(check( x == y )) == sizeof(yes) && sizeof(check( y == x )) == sizeof(yes);
96  };
97 
98  // Implementation for all comparisons template metafunction.
99  template <class T ,class U>
100  struct is_comparable_impl
101  {
102  static typename std::remove_cv<typename std::remove_reference<T>::type>::type const& x;
103  static typename std::remove_cv<typename std::remove_reference<U>::type>::type const& y;
104  static const bool value = sizeof(check( x == y )) == sizeof(yes) && sizeof(check( y == x )) == sizeof(yes) &&
105  sizeof(check( x < y )) == sizeof(yes) && sizeof(check( y < x )) == sizeof(yes) &&
106  sizeof(check( x > y )) == sizeof(yes) && sizeof(check( y > x )) == sizeof(yes) &&
107  sizeof(check( x <= y )) == sizeof(yes) && sizeof(check( y <= x )) == sizeof(yes) &&
108  sizeof(check( x >= y )) == sizeof(yes) && sizeof(check( y >= x )) == sizeof(yes);
109  };
110 
111  // Implementation for operable template metafunction.
112  template <class T ,class U>
113  struct has_arithmetic_impl
114  {
115  static typename std::remove_cv<typename std::remove_reference<T>::type>::type const& x;
116  static typename std::remove_cv<typename std::remove_reference<U>::type>::type const& y;
117  static const bool value = sizeof(check( x + y )) == sizeof(yes) && sizeof(check( y + x )) == sizeof(yes) &&
118  sizeof(check( x - y )) == sizeof(yes) && sizeof(check( y - x )) == sizeof(yes) &&
119  sizeof(check( x * y )) == sizeof(yes) && sizeof(check( y * x )) == sizeof(yes) &&
120  sizeof(check( x / y )) == sizeof(yes) && sizeof(check( y / x )) == sizeof(yes);
121  };
122 
123  // Implementation for assign_operable template metafunction.
124  template <class T ,class U>
125  struct has_assign_arithmetic_impl
126  {
127  static typename std::remove_cv<typename std::remove_reference<T>::type>::type & x;
128  static typename std::remove_cv<typename std::remove_reference<U>::type>::type & y;
129  static const bool value = sizeof(check( x += y )) == sizeof(yes) &&
130  sizeof(check( x -= y )) == sizeof(yes) &&
131  sizeof(check( x *= y )) == sizeof(yes) &&
132  sizeof(check( x /= y )) == sizeof(yes);
133  };
134 
135  // Implementation for promotable template metafunction.
136  template <class T ,class U>
137  struct is_promotable_impl
138  {
139  static typename std::remove_cv<typename std::remove_reference<T>::type>::type const& x;
140  static typename std::remove_cv<typename std::remove_reference<U>::type>::type const& y;
141  static const bool value = sizeof(check( x * y )) == sizeof(yes) && sizeof(check( y * x )) == sizeof(yes);
142  };
143  }
144 
145  //define some type_traits
146  template <class T, class U>
147  struct is_equality_comparable : function_existence_helper::is_equality_comparable_impl<T,U> {};
148  template <class T, class U> struct is_equality_comparable<T*,U*> { static const bool value = 0; };
149  template <class T> struct is_equality_comparable<T,void> { static const bool value = 0; };
150  template <class U> struct is_equality_comparable<void,U> { static const bool value = 0; };
151  template <> struct is_equality_comparable<void, void> { static const bool value = 0; };
152 
153  template <class T, class U>
154  struct is_comparable : function_existence_helper::is_comparable_impl<T,U> {};
155  template <class T, class U> struct is_comparable<T*,U*> { static const bool value = 0; };
156  template <class T> struct is_comparable<T,void> { static const bool value = 0; };
157  template <class U> struct is_comparable<void,U> { static const bool value = 0; };
158  template <> struct is_comparable<void, void> { static const bool value = 0; };
159 
160  template <class T, class U>
161  struct has_arithmetic : function_existence_helper::has_arithmetic_impl<T,U> {};
162  template <class T, class U> struct has_arithmetic<T*,U*> { static const bool value = 0; };
163  template <class T> struct has_arithmetic<T,void> { static const bool value = 0; };
164  template <class U> struct has_arithmetic<void, U> { static const bool value = 0; };
165  template <> struct has_arithmetic<void, void> { static const bool value = 0; };
166 
167  template <class T, class U>
168  struct has_assign_arithmetic : function_existence_helper::has_assign_arithmetic_impl<T,U> {};
169  template <class T, class U> struct has_assign_arithmetic<T*,U*> { static const bool value = 0; };
170  template <class T> struct has_assign_arithmetic<T,void> { static const bool value = 0; };
171  template <class U> struct has_assign_arithmetic<void,U> { static const bool value = 0; };
172  template <> struct has_assign_arithmetic<void, void> { static const bool value = 0; };
173 
174  template <class T, class U>
175  struct is_promotable : function_existence_helper::is_promotable_impl<T,U> {};
176  template <class T, class U> struct is_promotable<T*,U*> { static const bool value = 0; };
177  template <class T> struct is_promotable<T,void> { static const bool value = 0; };
178  template <class U> struct is_promotable<void,U> { static const bool value = 0; };
179  template <> struct is_promotable<void, void> { static const bool value = 0; };
180 }
181 
182 #endif // INCLUDE_NRT_CORE_TYPING_DETAILS_TYPETRAITSHELPERS_H