// (by Ariel Badichi) #include <boost/static_assert.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/add_reference.hpp> #include <boost/type_traits/add_const.hpp>
template<typename T> struct add_const_ref { typedef typename boost::add_const<T>::type ct; typedef typename boost::add_reference<ct>::type type; };
template<typename T1, typename T2> void same() { const bool v = boost::is_same<T1, T2>::value; BOOST_STATIC_ASSERT(v); }
int main() { same<const char &, add_const_ref<char>::type>(); same<int * const &, add_const_ref<int *>::type>(); same<int &, add_const_ref<int &>::type>(); same<const long &, add_const_ref<const long &>::type>(); return 0; }
// My metafunction is just a bit different. // Above method makes better use of available tools, this one is more from scratch.
template<typename T, bool B = is_reference<T>::value > struct add_const_ref; template<typename T> struct add_const_ref<T, true> { typedef T type; }; template<typename T> struct add_const_ref<T, false> { typedef T const& type; };
// by Zedd
template<typename T> struct add_const_ref { typedef T const& type ; } ;
template<typename T> struct add_const_ref<T&> { typedef T& type ; } ;
What if T is int const? As per this template add_const_ref<int const>::type result in "int const const &". Isn't that wrong?
// comment by avjewe No, it's exactly right, in that this is true :
boost::is_same<add_const_ref<int const>::type, int const &>::type::valueTo me, this is clearly the "correct" answer.
// by JCR
The first solution does not seem satisfying because a reference to an int is going to become constant when it should not. I am not sure how the second solution works. My solution is below; I still find it quite complicated; any idea?
template<bool b> struct add_const_ref_ { };
template<> struct add_const_ref_<true> { template<typename T> struct type_ { typedef T type; }; };
template<> struct add_const_ref_<false> { template<typename T> struct type_ { typedef T const& type; }; };
template<typename T> struct add_const_ref { static const bool test = boost::is_reference<T>::type::value; typedef typename add_const_ref_<test>::template type_<T>::type type; };
template<typename T1, typename T2> struct Same { static const bool value = boost::is_same<T1, T2>::type::value; };
int main (int argc, char ** argv) { std::cout << Same<add_const_ref<int&>::type, int&>::value << std::endl;//1 std::cout << Same<add_const_ref<int&>::type, int const &>::value << std::endl;//0 std::cout << Same<add_const_ref<int*>::type, int * const &>::value << std::endl;//1 std::cout << Same<add_const_ref<int>::type, int const &>::value << std::endl;//1 std::cout << Same<add_const_ref<const int &>::type, const int &>::value << std::endl;//1 return 0; }
template<class T> class add_const_ref { public: typedef typename boost::add_reference < typename boost::add_const < typename boost::remove_reference < T >::type >::type >::type type; };
I used class and access control public because I personally dislike using "struct" for non-POD types. In the first example, the typedef ct is exposed so I nested the boost type traits. I think one could also have used private to avoid the nesting and still not expose the typedef ct.
-bessermt<e_@_mail>gmail.com