C++ 如果我通过通用引用接受一个参数,那么is_rvalue_reference和is_lvalue_reference中是否有一个是真的?

C++ 如果我通过通用引用接受一个参数,那么is_rvalue_reference和is_lvalue_reference中是否有一个是真的?,c++,c++17,rvalue-reference,rvalue,lvalue,C++,C++17,Rvalue Reference,Rvalue,Lvalue,这段代码是否可以同时打印两种格式 using namespace std; template<typename T> void foo(T&& t) { if constexpr (is_lvalue_reference_v<T>) { cout << "lv" << endl; } else if constexpr (is_rvalue_reference_v<T>) {

这段代码是否可以同时打印两种格式

using namespace std;
template<typename T>
void foo(T&& t) {
    if constexpr (is_lvalue_reference_v<T>) {
        cout << "lv" << endl;
    } else if constexpr (is_rvalue_reference_v<T>) {
        cout << "rv" << endl;
    } else {
        cout <<"neither" << endl;
    }
}
这段代码是否可以同时打印两种格式

using namespace std;
template<typename T>
void foo(T&& t) {
    if constexpr (is_lvalue_reference_v<T>) {
        cout << "lv" << endl;
    } else if constexpr (is_rvalue_reference_v<T>) {
        cout << "rv" << endl;
    } else {
        cout <<"neither" << endl;
    }
}

如果我通过通用引用接受一个参数,那么is_rvalue_reference和is_lvalue_reference中是否有一个是真的

参数t将具有右值引用类型或左值引用类型。另一方面,类型T将根据演绎和规则而有所不同。如果将is_左值/rvalue_引用改为is_左值/rvalue_引用,则永远无法执行else路径

这段代码是否可以同时打印两种格式

using namespace std;
template<typename T>
void foo(T&& t) {
    if constexpr (is_lvalue_reference_v<T>) {
        cout << "lv" << endl;
    } else if constexpr (is_rvalue_reference_v<T>) {
        cout << "rv" << endl;
    } else {
        cout <<"neither" << endl;
    }
}
是,在将右值传递给foo且未给出显式模板参数时,都不会打印这两个值:

foo(42);  // "neither" is printed because T is deduced as int
或者当显式指定了非引用类型时:

int i=0;
// "neither" is printed because T is explicitly specified as int:
foo<int>(std::move(i));
虽然T可以是非引用类型,但T的类型将始终是引用类型。t类型有三种可能性:

T是一种值类型,即int:T的类型是int&;对int的右值引用。 T是一个左值引用,即int&:T的类型是int&&,它折叠为int&;对int的左值引用。 T是一个右值引用,即int&&:T的类型是int&&&,它折叠为int&;对int的右值引用。 这是转发引用的工作机制。如果将右值传递给foo,那么T将被推断为值类型。如果您传递一个左值,那么T将被推断为左值引用类型

这段代码是否可以同时打印两种格式

using namespace std;
template<typename T>
void foo(T&& t) {
    if constexpr (is_lvalue_reference_v<T>) {
        cout << "lv" << endl;
    } else if constexpr (is_rvalue_reference_v<T>) {
        cout << "rv" << endl;
    } else {
        cout <<"neither" << endl;
    }
}
对。根据类型推断规则,当传递左值时,T将被推断为左值引用类型,当传递右值时,T将被推断为非引用类型。e、 g

int i;
foo(i); // T is deduced as int&
foo(0); // T is deduced as int
另一方面,除非明确指定模板参数,否则不会打印rv

另一方面,如果检查函数参数t的类型,它将是左值引用类型或右值引用类型;两者都不会被打印出来

int i;
foo(i);        // T is deduced as int&, the type of t is int& (int& && -> int&)
foo(0);        // T is deduced as int, the type of t is int&&
foo<int&&>(0); // T is specified as int&&, the type of t is int&& (int&& && -> int&&)

另一方面,is_左值_reference_v和is_右值_reference_v中正好有一个是真的@宋元耀啊,对不起。@L.F.很好。我明白你的意思了。答案很好,但我想你应该注意,fooi将无法编译,所以它不会打印任何内容。传递std::movei解决了这个问题。@johanneschaub litb Heh,它本来有std::move,但我想让它这样做,显式参数不同于推导出来的参数并破坏它。把它加回去。