Why can't I check for a r-value-reference with a requires-constraint?

Viewed 54
#include <iostream>
#include <type_traits>
#include <utility>

using namespace std;

template<typename T>
    requires is_rvalue_reference_v<T>
void f( T &&v )
{
    T v2( forward<T>( v ) );
    cout << v << endl;
    cout << v2 << endl;
}

int main()
{
    string str = "hello world";
    f( move( str ) );
}

Why does this not compile until I remove the requires clause or: why doesn't the compiler notice that T is r-value-reference ?

1 Answers

As forwarding reference, when being passed rvalue T will be deduced as a non-reference type. For f( move( str ) );, T will be std::string (and the type of function parameter v will be std::string&&).

You can change the condition to:

template<typename T>
    requires is_rvalue_reference_v<T&&>
//                                  ^^
void f( T &&v )
{
    T v2( forward<T>( v ) );
    cout << v << endl;
    cout << v2 << endl;
}

For additional information, when being passed lvalue T will be deduced as lvalue-reference type. E.g. for f(str); T will be deduced as std::string& and T&& leads to std::string& too.

Related