Static member name lookup from generic lambda in member variable template initializer — compiler bug?

Viewed 78

The following code compiles on GCC and Clang, but not MSVC:

namespace ns {
    struct Foo {
        static void bar() { }

        template <int>
        static inline auto baz = [](auto) {
            bar();
        };
    };

    void(*qux)(int) = Foo::baz<42>;
}

MSVC outputs:

<source>(7): error C3861: 'bar': identifier not found
<source>(8): note: see reference to function template instantiation 'auto ns::<lambda_1339c3816c4e146ee6a49e0218a2a48b>::operator ()<_T>(_T) const' being compiled
        with
        [
            _T=int
        ]
<source>(8): note: see reference to function template instantiation 'auto ns::<lambda_1339c3816c4e146ee6a49e0218a2a48b>::<lambda_invoker_cdecl><_T>(_T)' being compiled
        with
        [
            _T=int
        ]
<source>(8): note: see reference to alias template instantiation 'ns::<lambda_1339c3816c4e146ee6a49e0218a2a48b>::<lambda_typedef_cdecl><int>' being compiled
<source>(8): note: while compiling class template member function 'ns::<lambda_1339c3816c4e146ee6a49e0218a2a48b>::operator unknown-type (__cdecl *)(_T1)(__cdecl *(void) noexcept const)(_T1)'

Any of these changes "fixes" the error:

  • Making the lambda non-generic
  • Making Foo::baz a non-template static member variable
  • Making Foo::baz a static function template that returns the lambda
  • Qualifying the call to bar as Foo::bar();
  • Removing ns, putting Foo and qux into the global namespace

This looks like a compiler bug to me. Is it one, or am I witnessing some kind of undefined or implementation-defined behaviour?

Live example on Godbolt

0 Answers
Related