barsdeveloper
barsdeveloper

Reputation: 960

Assign a lambda function to static member variable (c++)

I have a template class with a static member variable that I want to be a lambda function. Why doesn't it work?

#include <iostream>
using namespace std;

template <typename T>
class Test {
public:
    static constexpr auto lambda = [](T val) -> T {
        return val;
    };
};

int main() {
    cout << Test<int>::lambda(123) << endl;
}

I tried both version with constexpr and const.

In the first case I get:

../src/test.cpp:8:24: error: ‘constexpr const Test<int>::<lambda(int)> Test<int>::lambda’, declared using local type ‘const Test<int>::<lambda(int)>’, is used but never defined [-fpermissive]
  static constexpr auto lambda = [](T val) -> T {
                        ^~~~~~

In the second case:

../src/test.cpp:7:20: error: ‘constexpr’ needed for in-class initialization of static data member ‘const Test<int>::<lambda(int)> Test<int>::lambda’ of non-integral type [-fpermissive]
  static const auto lambda = [](T val) -> T {
                    ^~~~~~
../src/test.cpp:7:20: error: ‘const Test<int>::<lambda(int)> Test<int>::lambda’, declared using local type ‘const Test<int>::<lambda(int)>’, is used but never defined [-fpermissive]

Upvotes: 1

Views: 826

Answers (1)

DaveFar
DaveFar

Reputation: 7447

A core constant expression may contain a lambda only starting from C++17 (see cppreference point 8). This was proposal N24487 and got into C++17 as P0170R0.

If you have to use a static lambda, you can make use of the construct at first use idiom:

#include <iostream>

template <typename T>
class Test {
public:
    std::function<T(T)> createLambda() {
        static const std::function<T(T)> returnLambda = [](T val) -> T {
            return val;
        };
        return returnLambda;
    }
};

int main() {
    Test<int> lambdaFactory;
    std::function<int(int)> n = lambdaFactory.createLambda();
    std::cout << n(123) << std::endl;
}

Upvotes: 2

Related Questions