从rvalue参数中推导出对const的引用

时间:2011-05-20 16:43:33

标签: c++ templates reference const instantiation

好吧,这看起来似乎是一个愚蠢的问题,但在这里:

template <typename T>
void foo(T& x)
{
}

int main()
{
    foo(42);
    // error in passing argument 1 of 'void foo(T&) [with T = int]'
}

什么阻止C ++使用foo实例化T = const int功能模板?

3 个答案:

答案 0 :(得分:8)

问题是模板类型推导必须计算完全匹配,并且在特定情况下,由于签名中的引用,完全匹配需要左值。值42不是左值,而是右值,使用T解析const int不会产生完美匹配。由于模板类型扣除仅限于完全匹配,因此不允许扣除。

如果不是使用文字而是使用非可变左值,那么编译器将推导出适当的类型,因为const int将成为参数的完美匹配:

const int k = 10;
foo( k );            // foo<const int>( const int & ) is a perfect match

现在有一个特殊的规则可以调用一个带有r值的const引用(不可变的左值)的函数,这意味着创建一个临时的左值,后来绑定到引用,但是该规则可以启动函数必须具有该签名,这就是明确说明模板的类型为const int的原因:foo<const int>(42)

答案 1 :(得分:1)

他们的规则;-)。如果你让编译器从参数中推断出类型,它会选择最简单的东西。

这对我来说似乎并不合理。你的模板说它需要一个非const引用,所以它不能用rvalue编译。

您可以在通话网站上告诉它您的意思:foo<int const>(42);或更改您的模板以明确它不需要可变引用:template <typename T> void foo(T const & x) { }

在C ++ 11中,您有更多选项来表达您的模板将会接受和不接受的内容。

答案 2 :(得分:0)

无论是模板还是普通函数, rvalue都不能通过引用传递。 (所以const T&有效,但不是T&)。

What is preventing C++ to instantiate the foo function template with T = const int instead?

假设,C ++允许并生成T = const int。 现在有一段时间后你改变了foo,

template<typename T>
void foo (T& x)
{
  x = 0;
}

现在编译器必须生成错误。对于最终用户来说,体验会很奇怪,就像x = 0;之类的有效语句一样,它开始给出错误。这可能是编译器在第一阶段本身阻止的原因!