推导 lambda return 和传递给构造函数的参数
Deduce lambda return and arguments passed to constructor
我有以下 class:
template<typename R, typename... Args>
class Callable final
{
public:
Callable(void* args, R(*fn)(Args...));
Callable(void* args, std::function<R(Args...)> &&fn);
/* parse args into a tuple<Args...> and invoke callable */
void* invoke();
private:
void* args;
std::function<R(Args...)> callable;
};
我可以像这样使用它:
void* test(void* a, const char* b, const char* c)
{
return nullptr;
}
Callable(args, test).invoke();
Callable(args, std::function([](void* a, void* b, void* c){})).invoke();
但它不允许我这样做:
Callable(args, [](void* a, void* b, void* c){}).invoke();
//No viable constructor or deduction guide for deduction of template arguments of 'Callable'
我必须将 lambda
包裹在 std::function
中。有没有办法让我的 class 直接接受 lambda 并将其存储为 std::function
而无需显式指定 std::function(lambda)
作为构造函数参数?
我不想 Callable(args, std::function([](void* a, void* b, void* c){})).invoke();
将 lambda 显式包装在一个函数中。我想直接传递lambda,让构造器把它作为一个函数存储在内部。
我该怎么做?
如果允许我们修改 Callable
的模板签名以删除包 Args...
以支持单个参数,我们可以为 Callable
编写自己的推导指南:
template<typename Fn>
class Callable final {
public:
Callable(void* args, std::function<Fn>&&);
void* invoke();
private:
void* args;
std::function<Fn> callable;
};
template<typename>
struct Get_fn_type;
template<typename R, typename C, typename... Args>
struct Get_fn_type<R(C::*)(Args...) const> {
using type = R(Args...);
};
template<typename R, typename C, typename... Args>
struct Get_fn_type<R(C::*)(Args...)> { // for mutable lambdas
using type = R(Args...);
};
template<class Fn>
Callable(void*, Fn) -> Callable<
typename Get_fn_type<decltype(&Fn::operator())>::type>;
template<class Fn>
Callable(void*, Fn*) -> Callable<Fn>;
现在我们可以做:
Callable(args, test).invoke();
Callable(args, std::function([](void* a, void* b, void* c){})).invoke();
Callable(args, [](void* a, void* b, void* c) {}).invoke();
Callable(args, [](void* a, void* b, void* c) mutable {}).invoke();
使用一个模板参数而不是 pack 的一个缺点可能是难以明确定义 Args...
的元组。辅助类型特征可用于从 Fn
:
获取 std::tuple
类型
template<typename>
struct Tuple_from_args;
template<typename R, typename... Args>
struct Tuple_from_args<R(Args...)> {
using type = std::tuple<Args...>;
};
我有以下 class:
template<typename R, typename... Args>
class Callable final
{
public:
Callable(void* args, R(*fn)(Args...));
Callable(void* args, std::function<R(Args...)> &&fn);
/* parse args into a tuple<Args...> and invoke callable */
void* invoke();
private:
void* args;
std::function<R(Args...)> callable;
};
我可以像这样使用它:
void* test(void* a, const char* b, const char* c)
{
return nullptr;
}
Callable(args, test).invoke();
Callable(args, std::function([](void* a, void* b, void* c){})).invoke();
但它不允许我这样做:
Callable(args, [](void* a, void* b, void* c){}).invoke();
//No viable constructor or deduction guide for deduction of template arguments of 'Callable'
我必须将 lambda
包裹在 std::function
中。有没有办法让我的 class 直接接受 lambda 并将其存储为 std::function
而无需显式指定 std::function(lambda)
作为构造函数参数?
我不想 Callable(args, std::function([](void* a, void* b, void* c){})).invoke();
将 lambda 显式包装在一个函数中。我想直接传递lambda,让构造器把它作为一个函数存储在内部。
我该怎么做?
如果允许我们修改 Callable
的模板签名以删除包 Args...
以支持单个参数,我们可以为 Callable
编写自己的推导指南:
template<typename Fn>
class Callable final {
public:
Callable(void* args, std::function<Fn>&&);
void* invoke();
private:
void* args;
std::function<Fn> callable;
};
template<typename>
struct Get_fn_type;
template<typename R, typename C, typename... Args>
struct Get_fn_type<R(C::*)(Args...) const> {
using type = R(Args...);
};
template<typename R, typename C, typename... Args>
struct Get_fn_type<R(C::*)(Args...)> { // for mutable lambdas
using type = R(Args...);
};
template<class Fn>
Callable(void*, Fn) -> Callable<
typename Get_fn_type<decltype(&Fn::operator())>::type>;
template<class Fn>
Callable(void*, Fn*) -> Callable<Fn>;
现在我们可以做:
Callable(args, test).invoke();
Callable(args, std::function([](void* a, void* b, void* c){})).invoke();
Callable(args, [](void* a, void* b, void* c) {}).invoke();
Callable(args, [](void* a, void* b, void* c) mutable {}).invoke();
使用一个模板参数而不是 pack 的一个缺点可能是难以明确定义 Args...
的元组。辅助类型特征可用于从 Fn
:
std::tuple
类型
template<typename>
struct Tuple_from_args;
template<typename R, typename... Args>
struct Tuple_from_args<R(Args...)> {
using type = std::tuple<Args...>;
};