为什么右值引用模板变量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
2条答案
按热度按时间vs3odd8k1#
为什么右值引用模板变量
b<int>
能够绑定到左值a
?这个问题做出了一个不正确的假设。右值引用
b<int>
无法绑定到a
。使用您的实现,不会出现错误,因为decltype(b<int>)
本身不会导致b<int>
的示例化。这是好还是不好,有点不清楚。C++17标准草案的相应引用如下[temp.inst/6]:
除非变量模板专门化已经被显式地示例化或显式地专门化,否则变量模板专门化在使用专门化时被隐式地示例化。
根据这句话,我认为应该示例化
b
,因为使用了b<int>
(即使在未评估的上下文中)。然而,在目前的草案中,措辞有所不同[temp.inst/7/1]:
除非变量模板特化是声明的特化,否则当在需要变量定义存在的上下文中引用变量模板特化时,或者如果定义的存在影响程序的语义时,变量模板特化被隐式示例化。
无论如何,一旦你确定示例是必需的,你就会得到一个编译错误。
现场演示:https://godbolt.org/z/Ws5ajxWYM
htrmnn0y2#
根据 * 引用折叠规则 *,“右值引用到右值引用折叠到右值引用,所有其他组合形成左值引用”。虽然标准用其他的话来表述它(C++17标准草案[dcl.ref/6])。
因此,对于变量
b
:回到你的代码:
从这些文件中,只有
b<int&>
可以编译(演示Godbolt)。那么,为什么即使
b<int>
不能编译,decltype(b<int>)
也能通过编译呢?这是因为decltype
操作符只检查声明是否格式良好,而不执行任何示例化,因此不验证定义是否格式良好。请参阅丹尼尔的答案,以获得基于C++标准措辞的更深入的解释。