6

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?

rafalc
  • 203
  • 5
  • 9
  • I would guess if MSVC does not accept that then it is correct code and vice versa – Slava Jan 31 '18 at 19:23
  • 2
    This is definitely a MSVC bug. Even if the code is invalid, [the error that MSVC gives](https://learn.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-error-c2888) doesn't make sense here. – Justin Jan 31 '18 at 19:34
  • 4
    This is a MSVC bug. There is nothing in the standard that says generic lambdas can only be used in the global namespace. – Karl Jan 31 '18 at 19:39

1 Answers1

6

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

Ivan Sanz Carasa
  • 1,141
  • 8
  • 16