The problem is caused by reference decay: (correct term is "reference collapse")
template < typename T >
void f(T && t) { .... }
int x; f(x); // what is f()?
The answer to the question in the code is that f() is:
void f(T& && t) { .... }
Which because of reference decay turns into this:
void f(T& t) { .... }
As you can expect, this will of course be ambiguous with anything defined as:
template < typename T >
void f(T & t) { .... }
This might work (fixed version):
#include <type_traits>
#include <utility>
template < typename T >
struct pointer
{
pointer(T& t) {}
pointer(T&& t) {}
};
template < typename T >
pointer<typename std::remove_reference<T>::type>
address_of(T && t)
{
return pointer<typename std::remove_reference<T>::type>(std::forward<T>(t));
}
int main()
{
int x = 5;
pointer<int> o = address_of(x);
pointer<int> p = address_of(5);
}
The reason being that this reference decay stuff only happens in functions that are templated on T. In this case your pointer class is, but the constructors are not actually templates themselves and so T& is never a valid T for the T&& version.
The first version still had the same problem as your code since address_of was just using T as the template parameter for pointer. We actually need the raw type.
Noah Roberts
2010-07-02 16:37:53