|
iLab Neuromorphic Robotics Toolkit
0.1
|
00001 /*! @file 00002 @author Randolph Voorhies 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_PROMOTIONS_H 00037 #define INCLUDE_NRT_CORE_TYPING_PROMOTIONS_H 00038 00039 #include <nrt/Core/Typing/ErrorType.H> 00040 #include <nrt/Core/Typing/IntegerTypes.H> 00041 #include <nrt/Core/Typing/details/TypeTraitsHelpers.H> 00042 #include <type_traits> 00043 00044 namespace nrt 00045 { 00046 /*! \defgroup promotions Automatic type promotion for operations 00047 00048 When building generic functions it is often necessary to determine the return type of a generic method which takes 00049 two templated types as input. For example, what should be the return type of the following method? 00050 00051 @code 00052 template<class T1, class T2> 00053 Dims<SOME_TYPE> operator+(Dims<T1> x, Dims<T2> y); 00054 @endcode 00055 00056 A good solution is to use this nrt::promote class which determines the return type by asking the compiler in which 00057 type the result of T1*T2 (which is the largest data type returned by most operations) should be stored. The 00058 resulting code looks like this: 00059 00060 @code 00061 template<class T1, class T2> 00062 Dims<nrt::promote<T1,T2>::type> operator+(Dims<T1> x, Dims<T2> y); 00063 @endcode 00064 00065 Keep in mind that when trying to find an operator* the compiler will first try to match for the exact type, then 00066 for any implicit conversions, before getting eaten up by our fail mechanism. So, if you don't indend two types to 00067 be promotable but have constructors for one type that takes as an argument the other, make sure you make use of 00068 the explicit keyword in your constructors so the compiler can't implicitly convert it. See 00069 \link test-Traits.C \endlink 00070 00071 \ingroup typing */ 00072 00073 /*! @{ */ // ********************************************************************** 00074 00075 //! Specialization of nrt::promote for when we can't promote 00076 template <class T1, class T2, bool B = nrt::is_promotable<T1,T2>::value> 00077 struct promote 00078 { 00079 typedef NotATypeError type; 00080 static bool const will_promote = false; 00081 }; 00082 00083 //! Specialization of nrt::promote for when a promotion will occur 00084 template <class T1, class T2> 00085 struct promote<T1,T2,true> 00086 { 00087 private: 00088 static T1 const & x; 00089 static T2 const & y; 00090 00091 public: 00092 //! The nrt::promote::type typedef is used to access the resulting type of the promotion 00093 typedef decltype(x*y) type; 00094 00095 //! Will the resulting type be a different type than the two original types? 00096 static bool const will_promote = !(std::is_same<type, T1>::value && std::is_same<type, T2>::value); 00097 }; 00098 00099 //! Specialization of nrt::promote when first type is void, promoted type is the second type 00100 template <class T2> 00101 struct promote<void, T2, false> 00102 { 00103 typedef T2 type; 00104 static bool const will_promote = false; 00105 }; 00106 00107 //! Specialization of nrt::promote when second type is void, promoted type is the first type 00108 /*! This is useful if you want to not promote, for example: 00109 @code 00110 nrt::Image<nrt::PixGray<nrt::byte> > src; 00111 nrt::Image<nrt::PixGray<nrt::byte> > dest = nrt::lowPass3<void>(src); 00112 // by default, lowPass3() would return Image<PixGray<double>> as its default promo parameter is double 00113 @endcode */ 00114 template <class T1> 00115 struct promote<T1, void, false> 00116 { 00117 typedef T1 type; 00118 static bool const will_promote = false; 00119 }; 00120 00121 //! Specialization of nrt::promote when both types are void 00122 /*! This is just to avoid compilation ambiguities in the less-specialized cases. */ 00123 template <> 00124 struct promote<void, void, false> 00125 { 00126 typedef void type; 00127 static bool const will_promote = false; 00128 }; 00129 00130 /*! @} */ // ********************************************************************** 00131 } 00132 00133 #endif // INCLUDE_NRT_CORE_TYPING_PROMOTIONS_H