C++ 模板无法在不使用"&"的情况下推断引用类型

C++ Templates can't deduce Reference Types without using '&'

本文关键字:情况 下推 引用类型 情况下 C++      更新时间:2023-10-16

这是一个非常简单的例子:

#include <iostream>
template<typename T>
void DoubleMe(T x) {
    x += x;
}
int main()
{
    int a = 10;
    DoubleMe(a);
    std::cout << a; //displays 10 not 20!
}

在这种情况下,我是否被迫在函数参数中使用"T&"?因为我在一些教程中读到,模板可以通过在变量前定义一个简单的"T"来正确推断出适当的数据类型,包括 T*、T[ ] 或 T&。帮助?

也许这将帮助您以编译器的方式看待它(如果我过于简化,请向任何语言律师道歉(:

在此示例中,编译器必须推断 T 的类型是使函数声明合法且扣除量最少的类型。由于 T 通常可以直接从 const T&进行复制构造(这意味着它也可以从 T&进行复制构造(,因此您的函数将获取副本。

template<class T>
void foo(T value); 

在此示例中,T 必须是 ref 引用的对象事物的类型 - 并且由于引用不能引用引用,因此 T 必须是(可能是常量,可能是易失性(类型。

template<class T>
void foo(T& ref);

在此示例中,ref 必须引用类型 T 的 const(可能是易失性(对象:

template<class T>
void foo(const T& ref);

在此示例中,ref可以是引用 r 值引用。它被称为通用参考。您实际上是在一个函数中编写两个函数,这通常是处理您拥有ref的情况的最有效方法。

template<class T>
void foo(T&& ref);
// called like this:
foo(Bar());   // means ref will be a Bar&&
// called like this:
Bar b;
foo(b);       // means ref will be a Bar&
// called like this:
const Bar b;
foo(b);       // means ref will be a const Bar&

总结:

void foo(T value)的意思是我会复制你给我的东西。

void foo(T& value)意味着我不会复制,但我可能会修改您的值。你不许给我一个临时的

void foo(const T& value)意味着我不会复制,也无法修改您的副本。你可以给我一个临时的。

void foo(const T&& value)意味着我可以窃取或修改您的值的内容,即使它是暂时的

您确实可以使用普通T正确推断引用类型。不幸的是,这并不意味着你认为它的意思。

鉴于

template <typename T> struct S { };
template <typename T> void f(S<T>) { }
int main() { f(S<int&>{}); }

f的类型参数被正确地推导为 int&

问题是,在您的情况下,将T推断为int已经产生了一个完全有效的函数。也许有点过于简单,但类型推导会产生使调用工作的最简单的T。在您的情况下,T = int使呼叫正常工作。不是您希望它工作的方式,但编译器无法知道这一点。 T = int &也会使调用工作,但这不是使其工作的最简单的T

是的,要在此处获得所需的效果,必须添加与号。

编写时,模板可以正确推断数据类型。但是,他们无法推断出意图。在这种情况下,您传递给它的类型是一个整数,它正确地实例化了一个整数函数,该函数在内部按值将传递给它的参数加倍。事实上,你的意思是函数有副作用,这不是编译器可以猜到的。

如果希望函数按值传递参数,则需要返回具有相同参数类型的值。

T DoubleMe(T x) {
     return x + x;
 }