繁体   English   中英

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

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

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

#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正确推断引用类型。 不幸的是,这并不意味着您认为的意思。

给定

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的类型推断为以最小的推导量使函数声明合法的类型。 由于通常可以直接从const T&复制构造T(这意味着它也可以从T&复制构造),因此您的函数将复制一个副本。

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

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

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

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

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 DoubleMe(T x) {
     return x + x;
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM