Lamba depending on template depending value as default value of constructor of that template fails on MSVC

Viewed 39

I just upgraded my msvc and got into a trouble.

Here is Minimal Complete Verifiable Example which reproduce issue in my old code:

#include <functional>

#define VERSION 1

template<typename T>
class Foo
{
public:
    static constexpr int bar = 512;

#if VERSION == 1
    Foo(std::function<int()> f = []() { return Foo<T>::bar;})
#elif VERSION == 2
    Foo(std::function<int()> f = []() { return Foo::bar;})
#elif VERSION == 3
    Foo(std::function<int()> f = []() { return bar;})
#elif VERSION == 4
    Foo(std::function<int()> f = [bar = Foo<T>::bar]() { return bar;})
#endif
        : m_f{std::move(f)}
    {}

public:
    std::function<int()> m_f;
};


void use()
{
    Foo<int> foo;
}

Live demo

When VERSION is defined as 1 this is similar to my original code. I have to support also clang and gcc. Curretly my project is using C++17 standard (C++20 my project may use in next year or two).

I'm looking for some nice workaround which will not require nasty #if and cover all compilers (old new msvc gcc clang).

Other values of VERSION demonstrate what I have tried so far (always some compiler is failing).

VERSION which compilers fails
1 msvc 19.28
2 msvc 19.28, msvc 19.27, msvc 19.25
3 msvc all versions
4 clang 11.0

If someone knows respective bug report for MSVC link would be nice too.

Easiest fix is move constant to global scope, but I prefer to avoid that.

1 Answers

static function does the job:

static std::function<int()> defaultF() {return []() { return bar;};}

Foo(std::function<int()> f = defaultF())
    : m_f{std::move(f)}
{}

Demo

Related