I thought that these two functions should have had the same return type:
template<class T>
decltype(auto) f(T&& a){return a;}
decltype(auto) g(auto&& a){return a;}
Nevertheless, using gcc7, these functions verify:
int i;
static_assert(std::is_same< decltype(f(i)), int& >::value);
static_assert(std::is_same< decltype(g(i)), int >::value);
Why are the return types of g and f different?
The definition
decltype(auto) g(auto&& a){return a;}
is not Standard C++. It might be part of the upcoming Concepts Lite feature. g++ provides the syntax as an extension (even without -fconcepts
).
Compiling with -Wpedantic
in fact produces a warning:
warning: ISO C++ forbids use of 'auto' in parameter declaration [-Wpedantic]
decltype(auto) g(auto&& a){return a;}
^~~~
Since the behavior is not standardized yet, it is unclear whether your static_assert
should be truthy or not - intuitively I agree that decltype(g(i))
should be int&
though. This could simply be a "defect" in how g++ implements non-member function auto
parameters.
The closest Standard-compliant thing to what you're trying to do is a lambda expression:
auto z = [](auto&& a) -> decltype(auto) { return a; };
In the case of z
, the static_assert
works as expected:
static_assert(std::is_same< decltype(z(i)), int& >::value);