Consider following:
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
Both, gcc and clang throw error:
main.cpp:26:11: error: non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'
auto &t2 = test2(list);
^ ~~~~~~~~~~~
Shouldn't it work like with decltype? Why difference?
UPDATED
Wouldn't it be, in case with std::get, be equivalent to this? (I work with gcc 4.8)
template <class T>
auto&& test2(T &&brush) {
return std::get<0>( std::forward<T>(brush) );
}
auto only deduces the object type, meaning the the value-category of the object returned is not part of the return type.
Using the auto placeholder, type of the return statement is deduced by rules of template argument deduction:
§ 7.1.6.4/7auto specificer[dcl.spec.auto]If the placeholder is the auto type-specifier, the deduced type is determined using the rules for template argument deduction.
decltype(auto) on the other hand uses deduction as if by decltype():
§ 7.1.6.4/7auto specificer[dcl.spec.auto]If the placeholder is the
decltype(auto)type-specifier, the declared type of the variable or return type of the function shall be the placeholder alone. The type deduced for the variable or return type is determined as described in7.1.6.2, as though the initializer had been the operand of thedecltype.
So for perfect-forwarding return types, this is what you should use. Here's how it looks:
template <class T>
decltype(auto) test2(T &&brush) {
return std::get<0>(std::forward<T>(brush));
}
As a result, the return type will be an rvalue/lvaue-reference depending on the deduced type of brush.
I tested the above on Coliru, and it seems that g++ 4.8 can't compile the above code yet, though using clang++ it compiles fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With