模板推理和decltype(T)如何在refrence上工作?

时间:2018-06-12 16:27:27

标签: c++ templates reference

我正在用C ++学习模板。我不明白的是: 给定类型X并创建对象X a;,如果我通过a定义对X& b = 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
}

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

2 个答案:

答案 0 :(得分:3)

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

  

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

因此T推断为X。但是decltype(b)不仅仅是b作为表达式的类型。根据{{​​3}}(我无视相关部分):

  

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

     
      
  • ...

  •   
  • 否则,如果e是未加密码的 id-expression 或未加密码的类成员访问,decltype(e)由{{1}命名的实体的类型} 即可。 ...

  •   
  • ...

  •   

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

答案 1 :(得分:1)

试着回答&#34;为什么&#34; -part of the question:The function

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) { /* ... */ }

在调用时没有太多潜在的误解 - 参数通过引用传递。最后,这归结为整数是常规类型,而引用不是(参见this post最近的论文,也包括指针)。