Home > Enterprise >  C Template explicit rvalue type
C Template explicit rvalue type

Time:02-24

#include <iostream>

using namespace std;

namespace mine {

    template <typename T>
    struct remove_rval {
        using type = T;
    };

    template <typename T>
    struct remove_rval<T&&> {
        using type = T;    
    };

    template <typename T>
    void g(const T& = typename remove_rval<T>::type())
       cout << __PRETTY_FUNCTION__ << endl;        
    }
}

int main()
{
    
    mine::g<int&&>(); // doesn't work, because of explicit template?
    const int& i2 = mine::remove_rval<int&&>::type(); // works, sanity check
    
    return 0;
}

The function template I wrote fails to compile. From my understanding of c , you can assign an rvalue to a constant lvalue reference. But, in this situation, it is like the deduced type disregards the 'const' qualifier when assigning the function default value. Why is this?

CodePudding user response:

void g(const T& = typename remove_rval<T>::type())

Reference collapsing rules make const T& equal to U& when T = U&&. Lvalue-references can't bind to temporaries like remove_rval<T>::type(). You can instead simply pass int as a template argument and the parameter's type will correctly be const int&.

CodePudding user response:

From dcl.ref/p6:

If a typedef-name ([dcl.typedef], [temp.param]) or a decltype-specifier ([dcl.type.decltype]) denotes a type TR that is a reference to a type T, an attempt to create the type lvalue reference to cv TR creates the type lvalue reference to T, while an attempt to create the type rvalue reference to cv TR creates the type TR.

Thus in your example, when T = int&&: const T& becomes T&= int& and not const T& = const int& according to the above quoted statement. And since we can't bind an rvalue like remove_rval<T>::type() to a non-const lvalue reference, you get the mentioned error.

  • Related