iLab Neuromorphic Robotics Toolkit  0.1
include/nrt/Core/Typing/details/TypeTraitsHelpers.H
Go to the documentation of this file.
00001 /*! @file
00002     @author David J. Berg (dberg@usc.edu)
00003     @copyright GNU Public License (GPL v3)
00004     @section License
00005     @verbatim
00006     // ////////////////////////////////////////////////////////////////////////
00007     //              The iLab Neuromorphic Robotics Toolkit (NRT)             //
00008     // Copyright 2010-2012 by the University of Southern California (USC)    //
00009     //                          and the iLab at USC.                         //
00010     //                                                                       //
00011     //                iLab - University of Southern California               //
00012     //                Hedco Neurociences Building, Room HNB-10               //
00013     //                    Los Angeles, Ca 90089-2520 - USA                   //
00014     //                                                                       //
00015     //      See http://ilab.usc.edu for information about this project.      //
00016     // ////////////////////////////////////////////////////////////////////////
00017     // This file is part of The iLab Neuromorphic Robotics Toolkit.          //
00018     //                                                                       //
00019     // The iLab Neuromorphic Robotics Toolkit is free software: you can      //
00020     // redistribute it and/or modify it under the terms of the GNU General   //
00021     // Public License as published by the Free Software Foundation, either   //
00022     // version 3 of the License, or (at your option) any later version.      //
00023     //                                                                       //
00024     // The iLab Neuromorphic Robotics Toolkit is distributed in the hope     //
00025     // that it will be useful, but WITHOUT ANY WARRANTY; without even the    //
00026     // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR       //
00027     // PURPOSE.  See the GNU General Public License for more details.        //
00028     //                                                                       //
00029     // You should have received a copy of the GNU General Public License     //
00030     // along with The iLab Neuromorphic Robotics Toolkit.  If not, see       //
00031     // <http://www.gnu.org/licenses/>.                                       //
00032     // ////////////////////////////////////////////////////////////////////////
00033     @endverbatim */
00034 
00035 
00036 #ifndef INCLUDE_NRT_CORE_TYPING_DETAILS_TYPETRAITSHELPERS_H
00037 #define INCLUDE_NRT_CORE_TYPING_DETAILS_TYPETRAITSHELPERS_H
00038 
00039 namespace nrt
00040 {
00041   //! A set of type trait class to check if two types can be used in an arithmetic operation, or compared
00042   /*!
00043      See nrt::nrt_traits on how to use the function_existence_helper. The namespace supports classes which can be
00044      derived from to perform compile time checks for functions which take one or two arguments.
00045   */
00046   namespace function_existence_helper
00047   {
00048     // A type returned by the binary operator for any struct in this namespace
00049     // where T does not support the operator.
00050     struct no_support {};
00051 
00052     // These types soaks up any implicit conversions and makes the following
00053     // binary operator less preferred than any other such operator found duirng
00054     // the argument dependent lookup (ADL)
00055     struct any_class1 { template <class T> any_class1(T const&); };//can convert any type
00056     struct any_class2 { template <class T> any_class2(T const&); };//can convert any type
00057 
00058     // Fallback operators for when the binary operator for types T are not supported
00059     // use a macro here to help us define them for a bunch of operators
00060     no_support operator == (any_class1 const&, any_class2 const&);
00061     no_support operator < (any_class1 const&, any_class2 const&);
00062     no_support operator <= (any_class1 const&, any_class2 const&);
00063     no_support operator > (any_class1 const&, any_class2 const&);
00064     no_support operator >= (any_class1 const&, any_class2 const&);
00065 
00066     no_support operator + (any_class1 const&, any_class2 const&);
00067     no_support operator - (any_class1 const&, any_class2 const&);
00068     no_support operator * (any_class1 const&, any_class2 const&);
00069     no_support operator / (any_class1 const&, any_class2 const&);
00070     no_support operator += (any_class1 const&, any_class2 const&);
00071     no_support operator -= (any_class1 const&, any_class2 const&);
00072     no_support operator *= (any_class1 const&, any_class2 const&);
00073     no_support operator /= (any_class1 const&, any_class2 const&);
00074 
00075     // Two typedefs overloads to distinguish whether T supports a certain operator
00076     // expression.  The first typedef is a reference to a two-element character
00077     // array and is chosen if T does not support the expression. The second
00078     // overload returns a char and is chosen if T supports the expression. So
00079     // using sizeof(check(<expression>)) returns 2 for the first overload and 1
00080     // for the second overload.
00081     typedef char (&no)[2];
00082     typedef char yes;
00083 
00084     no check(no_support);
00085     template <class T> yes check(T const&);//this will be a bool most likely if an operator is found
00086 
00087     // Implementation for equality template metafunction.
00088     template <class T ,class U> 
00089     struct is_equality_comparable_impl
00090     {
00091         static typename std::remove_cv<typename std::remove_reference<T>::type>::type const& x;
00092         static typename std::remove_cv<typename std::remove_reference<U>::type>::type const& y;
00093         static const bool value = sizeof(check( x == y )) == sizeof(yes) && sizeof(check( y == x )) == sizeof(yes);
00094     };
00095 
00096     // Implementation for all comparisons template metafunction.
00097     template <class T ,class U> 
00098     struct is_comparable_impl
00099     {
00100         static typename std::remove_cv<typename std::remove_reference<T>::type>::type const& x;
00101         static typename std::remove_cv<typename std::remove_reference<U>::type>::type const& y;
00102         static const bool value = sizeof(check( x == y )) == sizeof(yes) && sizeof(check( y == x )) == sizeof(yes) &&
00103           sizeof(check( x < y )) == sizeof(yes) && sizeof(check( y < x )) == sizeof(yes) &&
00104           sizeof(check( x > y )) == sizeof(yes) && sizeof(check( y > x )) == sizeof(yes) &&
00105           sizeof(check( x <= y )) == sizeof(yes) && sizeof(check( y <= x )) == sizeof(yes) &&
00106           sizeof(check( x >= y )) == sizeof(yes) && sizeof(check( y >= x )) == sizeof(yes);
00107     };
00108 
00109     // Implementation for operable template metafunction.
00110     template <class T ,class U> 
00111     struct has_arithmetic_impl
00112     {
00113         static typename std::remove_cv<typename std::remove_reference<T>::type>::type const& x;
00114         static typename std::remove_cv<typename std::remove_reference<U>::type>::type const& y;
00115         static const bool value = sizeof(check( x + y )) == sizeof(yes) && sizeof(check( y + x )) == sizeof(yes) &&
00116           sizeof(check( x - y )) == sizeof(yes) && sizeof(check( y - x )) == sizeof(yes) &&
00117           sizeof(check( x * y )) == sizeof(yes) && sizeof(check( y * x )) == sizeof(yes) &&
00118           sizeof(check( x / y )) == sizeof(yes) && sizeof(check( y / x )) == sizeof(yes);
00119     };
00120 
00121     // Implementation for assign_operable template metafunction.
00122     template <class T ,class U> 
00123     struct has_assign_arithmetic_impl
00124     {
00125         static typename std::remove_cv<typename std::remove_reference<T>::type>::type & x;
00126         static typename std::remove_cv<typename std::remove_reference<U>::type>::type & y;
00127         static const bool value = sizeof(check( x += y )) == sizeof(yes) &&
00128           sizeof(check( x -= y )) == sizeof(yes) && 
00129           sizeof(check( x *= y )) == sizeof(yes) && 
00130           sizeof(check( x /= y )) == sizeof(yes);
00131     };
00132 
00133     // Implementation for promotable template metafunction.
00134     template <class T ,class U> 
00135     struct is_promotable_impl
00136     {
00137         static typename std::remove_cv<typename std::remove_reference<T>::type>::type const& x;
00138         static typename std::remove_cv<typename std::remove_reference<U>::type>::type const& y;
00139         static const bool value = sizeof(check( x * y )) == sizeof(yes) && sizeof(check( y * x )) == sizeof(yes);
00140     };
00141   }
00142 
00143   //define some type_traits
00144   template <class T, class U>
00145   struct is_equality_comparable : function_existence_helper::is_equality_comparable_impl<T,U> {};
00146   template <class T, class U> struct is_equality_comparable<T*,U*> { static const bool value = 0; };
00147   template <class T> struct is_equality_comparable<T,void> { static const bool value = 0; };
00148   template <class U> struct is_equality_comparable<void,U> { static const bool value = 0; };
00149   template <> struct is_equality_comparable<void, void> { static const bool value = 0; };
00150 
00151   template <class T, class U>
00152   struct is_comparable : function_existence_helper::is_comparable_impl<T,U> {};
00153   template <class T, class U> struct is_comparable<T*,U*> { static const bool value = 0; };
00154   template <class T> struct is_comparable<T,void> { static const bool value = 0; };
00155   template <class U> struct is_comparable<void,U> { static const bool value = 0; };
00156   template <> struct is_comparable<void, void> { static const bool value = 0; };
00157 
00158   template <class T, class U>
00159   struct has_arithmetic : function_existence_helper::has_arithmetic_impl<T,U> {};
00160   template <class T, class U> struct has_arithmetic<T*,U*> { static const bool value = 0; };
00161   template <class T> struct has_arithmetic<T,void> { static const bool value = 0; };
00162   template <class U> struct has_arithmetic<void, U> { static const bool value = 0; };
00163   template <> struct has_arithmetic<void, void> { static const bool value = 0; };
00164 
00165   template <class T, class U>
00166   struct has_assign_arithmetic : function_existence_helper::has_assign_arithmetic_impl<T,U> {};
00167   template <class T, class U> struct has_assign_arithmetic<T*,U*> { static const bool value = 0; };
00168   template <class T> struct has_assign_arithmetic<T,void> { static const bool value = 0; };
00169   template <class U> struct has_assign_arithmetic<void,U> { static const bool value = 0; };
00170   template <> struct has_assign_arithmetic<void, void> { static const bool value = 0; };
00171 
00172   template <class T, class U>
00173   struct is_promotable : function_existence_helper::is_promotable_impl<T,U> {};
00174   template <class T, class U> struct is_promotable<T*,U*> { static const bool value = 0; };
00175   template <class T> struct is_promotable<T,void> { static const bool value = 0; };
00176   template <class U> struct is_promotable<void,U> { static const bool value = 0; };
00177   template <> struct is_promotable<void, void> { static const bool value = 0; };
00178 }
00179 
00180 #endif // INCLUDE_NRT_CORE_TYPING_DETAILS_TYPETRAITSHELPERS_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines