如何将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
答案 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();
}