C ++将lambda传递给模板参数

时间:2017-02-01 18:37:16

标签: c++11 templates lambda

如何将lambda作为模板参数传递。
例如这段代码

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

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

失败,错误“'function'的模板参数无效,预期编译时常量表达式” 我做错了什么。

修改
我想实现类似的东西

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

2 个答案:

答案 0 :(得分:5)

C ++ 14中的Lambda,包括它们转换为函数指针,不是constexpr。

在C ++ 17中,this is going to change。没有稳定的编译器实现了我所知道的功能(如果你找到一个,你能否在下面的评论中提及它?)。

那时

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

肯定会奏效。我不确定是否

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

会起作用;在未评估的上下文和模板参数列表中有一些关于lambdas的规则,这些规则可能与constexpr lambda问题分开,可能适用于此处。

我们可以在C ++ 14中破解它。

创建一个存储lambda静态副本的模板类,并公开一个静态函数,该函数具有相同的签名(f_ptr),可以调用lambda的静态副本。

使用lambda全局实例化一次。

将指针f_ptr传递给您的模板。

所以:

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 >();

这几乎肯定不是你想要的。

答案 1 :(得分:0)

示例中的模板类型不会将类型作为参数,而是采用值。这个值需要在运行时可以确定,以便实例化模板,并且lambda的值不是编译时常量,所以这个方法不会这样做。将函子发送到函数的常用方法是:

template<typename Func>
void foo(Func&& f)
{
    f();
}

既然你想要一个类模板(请在问题中输入这些信息,而不是注释),这里有一个使用类的例子:

#include <utility>

template<typename Func>
class MyClass
{
public:
    MyClass(Func&& f) : f(f) {}
    void Run() { f(); }
private:
    Func f;
};

template<typename Func>
MyClass<Func> MakeMyClass(Func&& f)
{
    return { std::forward<Func>(f) };
}

int main()
{
    auto x = MakeMyClass( [](){} );
    x.Run();
}