c++11templateslambda

C++ Pass lambda to template parameter


How to pass lambda as template parameter.
For example this code

template<void (*callback)()>
void function() {
    callback();
}

int main() {
    function<[]() -> void { std::cout << "Hello world\n"; }>();
}

fails with error "invalid template argument for 'function', expected compile-time constant expression".
What I'm doing wrong.

Edit
I want to implement something like this

template<typename T,
        T (*deserializer)(buffer *data),
        void (*serializer)(T item, buffer *data)>
class Type {
public:
    T item;

    Type(T item) : item(item) {
    }

    Type(buffer *data) {
        deserialize(data);
    }

    void serialize(buffer *data) {
        serializer(item, data);
    }

    void deserialize(buffer *data) {
        deserializer(data);
    }
};

typedef Type<int, [](buffer* data) -> int { return -1; }, [](int item, buffer* data) -> void {}> IntType

typedef Type<long, [](buffer* data) -> long { return -1; }, [](long item, buffer* data) -> void {}> LongType

Solution

  • Lambdas in C++14, including their conversion to function pointers, are not constexpr.

    In C++17, this was changed, so now

    constexpr auto tmp = []() -> void { std::cout << "Hello world\n"; };
    function<+tmp>();
    

    will definitely work. I am uncertain if

    function<+[]() -> void { std::cout << "Hello world\n"; }>()
    

    would work; there are some rules about lambdas in unevaluated contexts and inside template argument lists that may be separate from the constexpr lambda problem and may apply here.

    We can hack it in C++14.

    Create a template class that stores a static copy of a lambda and exposes a static function with the same signature (f_ptr) that calls that static copy of a lambda.

    Instantiate it once globally with your lambda.

    Pass a pointer to the f_ptr to your template.

    So:

    template<class L> struct stateless; // todo
    template<class L> stateless<L> make_stateless(L l){return std::move(l);}
    
    auto foo = make_stateless( []() -> void { std::cout << "Hello world\n"; } );
    
    function< &foo::f_ptr >();
    

    this is almost certainly not what you want.