考虑以下几点:
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);
^ ~~~~~~~~~~~难道它不应该像解密那样工作吗?为什么不同?
更新
如果用std::get的话,它不是等同于这个吗?(我和gcc一起工作4.8)
template <class T>
auto&& test2(T &&brush) {
return std::get<0>( std::forward<T>(brush) );
}发布于 2014-06-10 22:46:13
auto只演绎对象类型,这意味着返回对象的值类别不是返回类型的一部分。
使用auto占位符,返回语句的类型由模板参数演绎规则推断:
§ 7.1.6.4/7auto specificer[dcl.spec.auto]如果占位符是自动类型-specifier,则使用模板参数演绎规则确定推导的类型。
另一方面,decltype(auto)使用的扣减方式就好像是由decltype()进行的。
§ 7.1.6.4/7auto specificer[dcl.spec.auto]如果占位符是decltype(auto)类型-specifier,则函数的变量或返回类型的声明类型仅为占位符。为变量或返回类型推导的类型是按照7.1.6.2中描述的那样确定的,仿佛初始化器是decltype的操作数。
因此,对于完美的转发返回类型,这是您应该使用的。以下是它的外观:
template <class T>
decltype(auto) test2(T &&brush) {
return std::get<0>(std::forward<T>(brush));
}因此,返回类型将是rvalue/lvaue引用,这取决于推导出的brush类型。
我在Coliru上测试了上面的代码,看来g++ 4.8还不能编译上面的代码,尽管使用clang++可以编译得很好。
发布于 2014-06-10 22:47:09
难道它不应该像解密那样工作吗?为什么不同?
它应该像decltype那样工作,但是在其他情况下,auto并不完全像decltype那样工作,而且他们不想使auto不一致。
相反,C++1y为惯用推导的函数返回类型引入了新的语法decltype(auto)。
https://stackoverflow.com/questions/24152017
复制相似问题