为什么右值引用模板变量能够绑定到左值

问题描述 投票:0回答:2

为什么右值引用模板变量

b<int>
能够绑定到左值
a

#include <iostream>

int a = 3;

template<typename T>
T&& b = a;

int main() {
    if(std::is_same_v<decltype(b<int>), int&&>) {
        std::cout << "same\n";
    } else {
        std::cout << "different\n";
    }
}
Output: same
c++ templates c++14 rvalue-reference
2个回答
3
投票

为什么右值引用模板变量

b<int>
能够绑定到左值
a

本题假设错误。右值引用

b<int>
无法绑定到
a
。通过您的实施,没有错误,因为
decltype(b<int>)
本身不会导致
b<int>
的实例化。

这是否可以有点不清楚。对应引用自C++17草案标准如下[temp.inst/6]:

除非变量模板特化已被显式实例化或显式特化,否则变量模板特化在使用特化时隐式实例化.

According to this quote,我认为应该实例化

b
,因为使用了
b<int>
(即使在未评估的上下文中)。

不过现在的草案,措辞不一样了[temp.inst/7/1]:

除非变量模板特化是声明的特化,否则当变量模板特化在需要变量定义存在的上下文中被引用时,或者定义的存在影响程序的语义时,隐式实例化

无论如何,一旦你确定实例是必需的,你就会得到一个编译错误。

现场演示:https://godbolt.org/z/Ws5ajxWYM


0
投票

我想从评论和大牛的回答中总结集体智慧

模板上下文中,

T&&
并不意味着r值引用而是转发引用(也称为通用引用)。将其视为以下替代(Godbolt 证明):

T = int    ==> T&& type is int&&
T = int&   ==> T&& type is int&
T = int&&  ==> T&& type is int&&

因此,在您的代码中:

template<typename T>
T&& b = a;

// On different instantiations this generates:
int&& b<int> = a;    // error, can't bind rvalue reference to lvalue
int& b<int&> = a;    // ok
int&& b<int&&> = a;  // error, can't bind rvalue reference to lvalue

因此,只有

b<int&>
会编译(演示 Godbolt)。

decltype(b<int>)
恰好通过编译的原因是
decltype
运算符 仅检查声明是否格式正确 但不进行任何实例化,因此 不验证定义是否格式正确。有关基于 C++ 标准措辞的更深入解释,请参阅 Daniel 的回答。

© www.soinside.com 2019 - 2024. All rights reserved.