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

tow*_*120 3 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);        
}
Run Code Online (Sandbox Code Playgroud)

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);        
          ^    ~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

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


更新

在这种情况下std::get,它不等于这个吗?(我使用gcc 4.8)

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

0x4*_*2D2 7

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

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

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

如果占位符是自动类型指定者,则使用模板参数推导的规则确定推导的类型.

decltype(auto)另一方面使用扣除,如下decltype():

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

如果占位符是decltype(auto) 类型指定者,则函数的声明类型或函数的返回类型应仅为占位符.对变量或返回类型推导出的类型如下所述确定7.1.6.2,好像初始化程序是操作数一样decltype.

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

template <class T>
decltype(auto) test2(T &&brush) {
    return std::get<0>(std::forward<T>(brush));
}
Run Code Online (Sandbox Code Playgroud)

因此,返回类型将是rvalue/lvaue-reference,具体取决于推导的类型brush.

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

  • 在别人做之前回答那些C++ 14问题变得越来越难了...... C++是否跳过了鲨鱼? (2认同)