C ++ 1y自动功能类型演绎

时间:2014-06-10 22:41:12

标签: c++ auto c++14

请考虑以下事项:

auto list = std::make_tuple(1, 2, 3, 4);

/// Work like a charm
template <class T>
auto test1(T &&brush) -> decltype(std::get<0>( std::forward<T>(brush) )) {
    return std::get<0>( std::forward<T>(brush) );
}


/// And now - C++14 feature
/// fail to compile - return value(temporary), instead of l-reference
template <class T>
auto test2(T &&brush) {
    return std::get<0>( std::forward<T>(brush) );
}

int main()
{
    auto &t1 = test1(list);
    auto &t2 = test2(list);        
}

http://coliru.stacked-crooked.com/a/816dea1a0ed3e9ee

两者,gcc和clang抛出错误:

main.cpp:26:11: error: non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'
    auto &t2 = test2(list);        
          ^    ~~~~~~~~~~~

它不应该像 decltype 一样工作吗?为什么不同?


已更新

如果std::get与...相同,那不是吗? (我使用gcc 4.8)

template <class T>
auto&& test2(T &&brush) {
    return std::get<0>( std::forward<T>(brush) );
}

2 个答案:

答案 0 :(得分:7)

auto只推导出对象类型,这意味着返回的对象的value-category不是返回类型的一部分。

使用auto占位符,返回语句的类型由模板参数推导规则推导出来:

  

§ 7.1.6.4/7 auto specificer [dcl.spec.auto]

     
    

如果占位符是auto type-speci fi er ,则使用模板参数推断规则确定推导出的类型。

  
另一方面,

decltype(auto)使用扣除,就像decltype()

一样
  

§ 7.1.6.4/7 auto specificer [dcl.spec.auto]

     
    

如果占位符是decltype(auto) 类型指定者,则声明的变量类型或函数的返回类型应仅为占位符。根据{{​​1}}中的描述确定为变量或返回类型推导出的类型,就像初始化程序是7.1.6.2的操作数一样。

  

因此,对于完美转发返回类型,这是您应该使用的。这是它的外观:

decltype

因此,返回类型将是rvalue / lvaue-reference,具体取决于推导出的template <class T> decltype(auto) test2(T &&brush) { return std::get<0>(std::forward<T>(brush)); } 类型。

我在Coliru上测试了上面的内容,似乎brush无法编译上面的代码,尽管使用clang++它编译得很好。

答案 1 :(得分:2)

  

它不应该像decltype一样工作吗?为什么不同?

它应该像decltype一样工作,但auto在其他情况下与decltype完全不同,并且他们不想制作auto不一致。

相反,C ++ 1y为惯用推导函数返回类型引入了新语法decltype(auto)