C ++模板无法使用'&'来推断参考类型。

时间:2015-12-28 14:44:31

标签: c++ templates

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

#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!
}

在这种情况下,我被迫使用&#39; T&amp;&#39;而在函数参数中呢? Cuz我在一些教程中读到模板可以正确地推导出适当的数据类型,包括T *,T []或T&amp;只需定义一个简单的T&#39;在变量之前。帮助

4 个答案:

答案 0 :(得分:6)

是的,要获得您想要的效果,您必须添加&符号。

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

答案 1 :(得分:5)

您确实可以使用普通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使它工作。

答案 2 :(得分:4)

也许这会帮助你按照编译器的方式来看待它(如果我过分简化,可以向任何语言律师道歉):

&#xA;&#xA;

在这个例子中,编译器必须推断T的类型是使函数声明合法且具有最小推论量的类型。由于T通常可以直接从const T&amp; amp; (这意味着它也可以从T&amp;复制构造),你的功能将采取副本。

&#xA;&#xA;
  template&lt; class T&gt;&#xA; void foo(T value); &#xA;  
&#xA;&#xA;

在这个例子中,T必须是 ref 引用的对象的类型 - 并且因为引用不能参考引用,T必须是(可能是const,可能是易失性的)类型。

&#xA;&#xA;
 模板&lt; class T&gt;&#xA; void foo(T&amp; ref );&#xA;  
&#xA;&#xA;

在这个例子中,ref必须引用类型为T的const(可能是易失性的)对象:

& #xA;&#xA;
  template&lt; class T&gt;&#xA; void foo(const T&amp; ref);&#xA;  
&#xA;&#xA ;

在此示例中, ref 可以 作为参考是r值引用。它被称为通用参考。您实际上是将两个函数合二为一,这通常是处理 ref 所有权的最有效方式。

&#xA;&#xA;
  template&lt; class T&gt;&#xA; void foo(T&amp;&amp; ref);&#xA;&#xA; //这样调用:&#xA; foo(Bar()); //表示ref将是一个&amp;&amp;&#xA;&#xA; //如下所示:&#xA; Bar b;&#xA; foo(b); //表示ref将是一个&amp;&#xA;&#xA; //这样调用:&#xA; const Bar b;&#xA; foo(b); //表示ref将是const Bar&amp;&#xA;  
&#xA;&#xA;

总结:

&#xA;&#xA;

void foo(T value)意味着我复制你给我的任何内容。

&#xA;&#xA;

void foo(T&amp; value)表示我不会制作副本,但我可以修改您的值。 你可能不会给我一个临时的

&#xA;&#xA;

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

&#xA;&#xA;

void foo(const T&amp;&amp; value)意味着我可能窃取或者修改你的价值内容,即使它是暂时的

&#xA;

答案 3 :(得分:0)

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

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