Hello, I am going through the book C++ Template Metaprogramming and wanted a sanity check on Exercise 2-0 from the book. My first question is: What would be a motivating example for why one would want a add_const_ref<T> metafunction that returned T if it was a reference and T const& otherwise? My second question is: How did I do? My guess is that the second crack is more correct. Here is crack one: My first crack at the exercise is below (my 2nd crack is below that) #include <iostream> #include <boost/type_traits/is_reference.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/static_assert.hpp> using namespace std; template<typename T, bool> struct add_const_ref { typedef T const& value_type; }; template<typename T> struct add_const_ref<T, true> { typedef T value_type; }; template<typename T> void func(typename add_const_ref<T, boost::is_reference<T>::value
::value_type t)
{ // .. do something } class BigClass { }; int main() { int i = 0; BOOST_STATIC_ASSERT((boost::is_same<add_const_ref<int&, boost::is_reference<int&>::value >::value_type, int&>::value)); BOOST_STATIC_ASSERT((boost::is_same<add_const_ref<int, boost::is_reference<int>::value >::value_type, int const&>::value)); func<int&>(i); BigClass myBigClass; func<BigClass>(myBigClass); return 0; } After taking a look at add_reference.hpp in boost I modified my answer to the one below: #include <iostream> #include <boost/type_traits/is_reference.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/static_assert.hpp> using namespace std; template<bool> struct const_ref_adder { template<typename T> struct result_ { typedef T const& value_type; }; }; template<> struct const_ref_adder<true> { template<typename T> struct result_ { typedef T value_type; }; }; template<typename T> struct add_const_ref { typedef typename const_ref_adder<boost::is_reference<T>::value
::template result_<T>::value_type value_type;
}; template<typename T> void func(typename add_const_ref<T>::value_type t) { // .. do something } class BigClass { }; int main() { int i = 0; BOOST_STATIC_ASSERT((boost::is_same<add_const_ref<int&>::value_type, int&>::value)); BOOST_STATIC_ASSERT((boost::is_same<add_const_ref<int>::value_type, int const&>::value)); func<int&>(i); BigClass myBigClass; func<BigClass>(myBigClass); return 0; } Thanks in advance for your input, Bruce
Trask, Bruce (US SSA) wrote:
Hello,
I am going through the book C++ Template Metaprogramming and wanted a sanity check on Exercise 2-0 from the book.
My first question is: What would be a motivating example for why one would want a add_const_ref<T> metafunction that returned T if it was a reference and T const& otherwise?
It's useful for forwarding function arguments. This document gives several examples of cases where one may want to do that: <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm>. Forwarding must be done by reference, but implementations are required to treat T & as ill-formed if T is a reference type, rather than treating it as being the same as T. add_const_ref<T> should yield the correct type to use for forwarding an argument of type T.
My second question is: How did I do? My guess is that the second crack is more correct. <snip>
Well the first attempt doesn't solve the problem because it requires an extra parameter. The second attempt solves it but I don't think you're supposed to make use of other templates. I think the expected solution would be more like this: template<typename T> struct add_const_ref { typename T const & type; }; template<typename T> struct add_const_ref<T &> { typename T & type; }; Ben.
Ben Hutchings wrote:
Well the first attempt doesn't solve the problem because it requires an extra parameter. The second attempt solves it but I don't think you're supposed to make use of other templates.
Any solutions is allowable, though that one is not particularly elegant.
I think the expected solution would be more like this:
template<typename T> struct add_const_ref { typename T const & type; };
template<typename T> struct add_const_ref<T &> { typename T & type; };
Actually there's a much more concise solution using the type traits library. That is, after all, the focus of the chapter. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com
David Abrahams wrote:
Ben Hutchings wrote:
Well the first attempt doesn't solve the problem because it requires an extra parameter. The second attempt solves it but I don't think you're supposed to make use of other templates.
Any solutions is allowable, though that one is not particularly elegant.
I think the expected solution would be more like this:
template<typename T> struct add_const_ref { typename T const & type; };
template<typename T> struct add_const_ref<T &> { typename T & type; };
Actually there's a much more concise solution using the type traits library. That is, after all, the focus of the chapter.
Remind me not to talk about books I haven't read in future... Ben.
participants (3)
-
Ben Hutchings
-
David Abrahams
-
Trask, Bruce (US SSA)