模板中的C ++ rvalue临时值

时间:2010-06-08 05:35:03

标签: c++ templates rvalue

您能否解释一下以下机制的区别:

int function();

template<class T>
void function2(T&);

void main() {
    function2(function()); // compiler error, instantiated as int &

    const int& v = function();
    function2(v); // okay, instantiated as const int&
}

我的推理在实例化方面是否正确? 为什么不首先实例化为const T&

谢谢

4 个答案:

答案 0 :(得分:3)

因为function返回非const值。只有对象可以是const,因为它们存储了一些可以修改的状态,如果它不是const的话。你返回的不是一个对象,而是一个纯粹的价值。从概念上讲,它们不可修改(例如枚举常量),但它们不是const限定的(再次,枚举常量)。

答案 1 :(得分:2)

我认为你可能会在rvalues和const限定符之间感到困惑。 function返回一个int类型的非const rvalue临时,因此编译器将T推导为int,就像它应该的那样。正如您所指出的,您可以将临时绑定到const ref(c ++ 03 12.2 / 5),但编译器不会添加cv限定符以使函数调用格式良好。由于您无法控制模板功能,因此有两种方法(除了您发布的解决方案)。

(1)明确的模板参数:function2<const int>(function())

(2)cv限定返回:const int function();

这两种解决方案都很好。 (1)似乎是更好的解决方案,恕我直言,因为(2)是非常规和愚蠢的。

编辑:实际上,推导出的类型可以比ref模板参数的参数更加cv限定,但只有在类型推导失败时才会失败(c ++ 03 14.8.2.1/3)。在这种情况下,类型推导不会失败,但会导致格式错误的函数调用(SFINAE不适用,因为模板函数特化本身不会格式错误)。

如果模板作者的意图是不修改参数,那么它应该被声明为const引用参数,所以这可能是模板库中的一个bug,或者它可能会修改参数,在这种情况下你是什么在函数尝试修改参数时,正在执行的操作将失败。

编辑:正如FredOverflow指出的那样,非类别的右值总是cv不符合标准3.10 / 9。所以(2),它在gcc 4.3下工作,实际上是一个编译器错误(gcc&lt; 4.5,根据FredOverflow)。

答案 2 :(得分:0)

在这一行

function2(function()); 

在function2返回之后,传递给它的参数可能会改变它的值,但是因为function()返回并且它刚刚被分配给一个临时变量,但是这个临时变量超出范围后会发生什么呢?问题,这就是编译器投诉的原因。

答案 3 :(得分:0)

要编译第一个调用,必须使用T&amp;&amp ;;定义function2。参数 - 这是rvalue,对临时对象的引用。在第二次调用中,v是左值引用,可以。如果您的编译器不支持rvalue引用,则第一次调用可能只使用T参数编译,不带引用。