Today, I stumbled across the following code snippet:
#include <utility>
int main()
{
auto a = [](std::pair<auto, auto> value)
{
};
a(std::pair<int, bool>{ 3, true });
}
I have only one question: is this code supported by the standard?
It compiles in GCC (with -std=c++14
), but not clang or Visual Studio 2015 (VC++14).
This seems like it should be part of the standard because if lambdas should have the same template support as regular functions, then this should be supported.
This seems to convert to all template types, not just std::pair
.
In C++14, auto
is not allowed in template arguments, whether in a lambda or not. Clang and Visual Studio are both right to reject this code.
The C++14 standard reference is [dcl.spec.auto]. The auto
specifier is allowed in the following contexts:
auto f();
) (paragraph 2)operator auto()
in a class) (paragraph 2)auto f() -> auto;
) (paragraph 2)if
or switch
statement or a loop (paragraph 5)new
expression, i.e., new auto(42)
(paragraph 5)Finally,
A program that uses
auto
ordecltype(auto)
in a context not explicitly allowed in this section is ill-formed.
Therefore, auto
is not allowed in template parameters, since that case isn't enumerated in [dcl.spec.auto].
I don't know why gcc allows it. It might be related to Concepts Lite, but I don't know if Concepts Lite actually allows this usage. It could just be an unrelated extension that is easy to implement. I assume that
[](std::pair<auto, auto> value) { /* ... */ }
is translated into
struct __some_unique_name {
template <typename T1, typename T2>
auto operator()(std::pair<T1, T2> value) const { /* ... */ }
// ...
};