iLab Neuromorphic Robotics Toolkit  0.1
include/nrt/Core/Typing/Promotions.H
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines