模板推导和 decltype(T) 如何在引用上工作?

How does the template deduction and decltype(T) works on a refrence?

本文关键字:引用 工作 decltype      更新时间:2023-10-16

我正在学习C++模板。我不明白的是: 给定一个类型X,并创建一个对象X a;,如果我通过X& b = a;定义对a的引用,则std::is_reference<decltype(b)>::value返回true。但是,我是否将b作为模板函数的参数,扣除的类型不是引用。

#include <iostream>
class X {};
template<typename T>
void
F(T t)
{
if (std::is_reference<T>::value)
std::cout << "T is a reference" << std::endl;
}
int
main()
{
X a;
X &b = a;
std::cout << std::is_reference<decltype(b)>::value << std::endl; // return true
F(b); //return false
}

我的问题是为什么代码是这样工作的。

由于[expr.type]/1,b作为表达式的类型X

如果表达式最初具有类型"引用 T"([dcl.ref], [dcl.init.ref](,则在进行任何进一步分析之前,该类型将调整为 T。

所以T被推断为X.然而,decltype(b)不仅仅是作为表达式的b类型。根据 [dcl.type.simple]/4(我不相关的部分被我省略了(:

对于表达式e,用decltype(e)表示的类型定义如下:

  • 否则,如果 e 是无括号的id 表达式或无括号的类成员访问,则decltype(e)是由e命名的实体的类型。

请注意,它是按b命名的实体的类型(即X&(,而不是表达式的类型b

试图回答问题的"为什么"部分:函数

void someFunc(int arg) { /* ... */ }

显然通过值接收其参数。考虑到int,您期望从此函数中获得什么样的语义?

template<class T> void someFunc(T arg) { /* ... */ }

我希望该参数也按值传递。现在考虑调用片段,在第一种情况下

int i;
int& j = i;
someFunc(j); /* j passed by value. */

在第二种情况下

X a;
X& b = a;
someFunc(b); /* b passed by reference? Luckily not. */

使用函数模板签名改为

template<class T> someFunc(T& arg) { /* ... */ }

在调用时没有太多潜在的误解 - 参数是通过引用传递的。最后,这归结为整数是常规类型,而引用不是(请参阅这篇文章以获取最近的论文,也涵盖了指针(。