1

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]
4
  • The 1st case will work fine with C++17. Commented Mar 25, 2017 at 9:50
  • Thank you! I will find a work around. Commented Mar 25, 2017 at 9:54
  • Why don't you simply use a static function? ...after all there will be different of such for each separate instantiation of Test.. Commented Mar 25, 2017 at 10:03
  • Because I need to refer to the function with a very short name, like n(arg) and variable assignment is a very intuitive concept. Instead, by using a static function the user should define a reference n to Test<int>::myFunction. I didn't even know function reference existed until now. Commented Mar 25, 2017 at 10:07

1 Answer 1

2

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

If you've got C++14 deduced return types, you can probably get rid of the std::function wrapper.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.