考虑以下:
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)
auto 只推导出对象类型,这意味着返回的对象的value-category不是返回类型的一部分.
使用auto占位符,return语句的类型由模板参数推导规则推导:
§ 7.1.6.4/7auto specificer[dcl.spec.auto]如果占位符是自动类型指定者,则使用模板参数推导的规则确定推导的类型.
decltype(auto)另一方面使用扣除,如下decltype():
§ 7.1.6.4/7auto 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++它编译得很好.