Consider the following piece of code
#include <iostream>
#include <functional>
namespace A {
template<typename T>
struct X {
using Function = std::function<int(T)>;
static Function f;
};
template<typename T>
typename X<T>::Function X<T>::f = [](auto) { return 42; };
}
int main() {
std::cout << A::X<int>::f(0);
}
Both GCC and clang accept this code but MSVC (tested version 19.00.23506) gives:
error C2888: 'auto <lambda_ce48e25aa4b9e3d225584044e4eae9e2>::operator ()(_T1) const': symbol cannot be defined within namespace 'A'
And indeed, if I remove namespace A and define everything in the global namespace, the code is accepted. Same if I make lambda expression non-generic.
Can someone explain what is the problem that MSVC sees in this code? Does C++ Standard restrict usage of generic lambdas in contexts like above?
Generic lambdas were introduced in C++14 . Simply, the closure type defined by the lambda expression will have a templated call operator rather than the regular, non-template call operator of C++11 's lambdas (of course, when auto appears at least once in the parameter list).
Instances of std::function can store, copy, and invoke any CopyConstructible Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.
Yes, this is a MSVC bug but it has been fixed on VS2017 15.6 preview 2.0
There is no specification in the standard that restricts generic lambdas to exist only in the global namespace.
POC of the problem can be found here: https://godbolt.org/g/BESMK4
MSVC is not able to deduce that auto
is exactly T
in every case, and fails.
In case you need to make it work with MSVC, replace auto
with explicit T
:
template<typename T>
typename X<T>::Function X<T>::f = [](T) { return 42; };
https://godbolt.org/g/cYG9GC
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