简体   繁体   中英

Why can't I bind an lvalue-reference to an rvalue while a concept can?

#include <utility>

template<typename T>
concept IsWritable = requires(T& obj)
{
    obj = 0;
};

template<typename T>
void f(T&)
{}

int main()
{
    static_assert(IsWritable<int&&>); // ok
    
    int n = 0;
    f(std::move(n)); // error
}

GCC error message:

error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 
       'std::remove_reference<int&>::type' {aka 'int'}

Why can't I bind an lvalue-reference to an rvalue while a concept can?

Given

template<typename T>
void f(T&)
{}

the line

    f(std::move(n)); // error

must error, because you're trying to pass an rvalue argument, std::move(n) , to a lvalue reference parameter, T& .

As regards the concept, notice that there's no argument-parameter pair on the value level . And it's on the value level that talking about rvalue/lvalue-ness makes sense (after all, those are called value categories ).

There's an argument-parameter pair on the type level, though: you're explicitly passing the int&& template argument to IsWritable 's template argument T , so the T& will be int&& & , which is int& , because normal reference collpasing applies (it doesn't just apply to universal references).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM