I have compilers disagreeing on a small C++14 code snippet:
#include <cassert>
struct unmovable {
unmovable() {}
unmovable(unmovable&&) = delete;
};
int main()
{
unmovable u;
auto i = [&]() -> decltype(auto) { return u; };
auto& uu = i();
assert(&uu == &u);
}
The program is accepted by g++4.9.3, g++-5.1.0, g++-5.2.0 and VisualStudio 2015, but not by clang++-3.7.
clang++-3.7 deduces the return type to be unmovable
(value) and not unmovable&
.
If the program is changed slightly, so that the variable u
is global, then all compilers agree on the error.
As I understand it, the captured u
in the lambda should be of type unmovable&
when the variable is local.
I don't have the C++14 standard, but hopefully the draft from github is relevant. My interpretation of 7.1.6.2 and 7.1.6.4 is that decltype(auto)
becomes decltype(u)
from the return, which in the global case should be unmovable
(value) and in the lambda reference capture of the local u
, it should become unmovable&
since the captured variable must be of type unmovable&
. This would indicate that clang++ got it wrong.
If I change the lambda and its use slightly:
auto i = [](auto& v) -> decltype(auto) { return v; };
auto& uu = i(u);
then all compilers accept it, regardless of whether u
is global or local, which I think strengthens my interpretation of the decltype(auto)
deduction, since v
here definitely becomes of type unmovable&
.
Is my interpretation correct and thus clang++ incorrect?
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