c++visual-studio-2013universal-reference

VS 2013 fails to specialize function template with universal reference and return type depending on template parameter


VS 2013 says that it cannot specialize the function template in the following code:

struct W { };

template <class T>
typename T::result_type
f (const W & w, T && t) {
    return 0;
}

/* ... */
struct V { typedef int result_type; };

W w {};
V v {};
f (w, v);

If I replace typename T::result_type by int or if I replace the universal reference T&& by T&, it does not complain.

In my opinion, the above code is correct. Is this a compiler bug, or am I doing anything wrong?


Solution

  • The compiler is right. The way forwarding references(1) work is that if passed an lvalue of type U, they use U& instead of U for type deduction. Since v in your case is an lvalue, T is deduced to V&. V& is a reference type, it doesn't have a nested type (it cannot even have one).

    When working with forwarding references, you have to always use std::remove_reference to get at the underlying type:

    template <class T>
    typename std::remove_reference<T>::type::result_type
    f (const W & w, T && t) {
        return 0;
    }
    

    (1) Since CppCon 2014, "forwarding reference" was accepted as replacement term for "universal reference," since it captures the intent better.