![](/img/trans.png)
[英]template class specialization - how to pass the template argument to constructor?
[英]How to pass template parameter from class constructor
我有模板 class 和一些使用它的策略。 它只是执行具有特定策略的 lambda。
template<template<class>class Policy, typename ReturnType>
class execute :Policy<ReturnType>
{
public:
ReturnType res;
execute(ReturnType(*func)())
{res = Policy<ReturnType>().launch(func);}
};
template<typename ReturnType>
struct Policy1 {
ReturnType launch(ReturnType(*func)())
{/*some code*/
return func();}
};
template<typename ReturnType>
struct Policy2 {
ReturnType launch(ReturnType(*func)())
{/*some code*/
return func();}
};
int main()
{
auto lambda_int = [] {return int(1); };
auto lambda_float = [] {return float(1.0); };
execute<Policy1, decltype(lambda_int())> exec1(lambda_int);
execute<Policy2, decltype(lambda_float())> exec2(lambda_float);
}
客户端代码正是我需要的。 但是我两次指向 lambda 并且我想将客户端代码中的 class 变量声明减少到此:
execute<Policy1> exec3(lambda_float);
据我了解,我不能使用类似tempalte<auto ReturnType>
的东西,因为它只适用于单个参数。 我也不能使用默认参数,因为我想传递任何类型的 lambda 返回。
template<template<class>class Policy, typename ReturnType=int>
class execute :Policy<ReturnType>
问题是如何将 function 返回类型(即构造函数参数)传递给 class 模板 arguments? 或者可能有另一种方式?
更新:基于Secundi的回答。
template<template<class>class Policy, typename FunctorType>
auto create_executor(FunctorType f)
{
return execute<Policy, decltype(f())>(f);
}
int main(){
auto ce5 = create_executor<Policy2>(lambda_int);
}
我不知道您的示例代码与实际代码有多少偏差,但如果我从表面上看,我会重新组织它。
我的第一个观察是您的Policy
不必是模板 class。 它没有任何需要类级模板的成员。 相反, launch
function 可以成为模板:
struct Policy {
template <class Callable>
auto launch(Callable&& callable) {
/*some code*/
return callable();
}
};
现在,您的execute
没有理由从Policy
继承(这对于策略类型设计来说也是非惯用的)。
我们还剩下你的 lambda 型扣未解决。 理想情况下,我们将使用 class 模板参数推导,我们可以,考虑到上面所说的一切,这是我将如何更改您的execute
:
template<class Policy, class Callable>
struct execute {
using ResultType = std::invoke_result_t<Callable>;
execute(Policy&&, Callable&& callable)
{
res = Policy().launch(std::forward<Callable>(callable));
}
ResultType res;
};
你可以这样使用它:
void foo()
{
execute exec{Policy{}, [](){ return 10; }};
}
标准说:
Class 模板参数推导仅在不存在模板参数列表时执行。 如果指定了模板参数列表,则不会进行推导。
因此,您无法做到这么简单,尽管乍一看该功能是有意义的。
通过不影响您当前 class 设计的 function 模板助手的关闭解决方案:
#include <cstddef>
#include <tuple>
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
enum { arity = sizeof...(Args) };
// arity is the number of arguments.
typedef ReturnType result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
// the i-th argument is equivalent to the i-th tuple element of a tuple
// composed of those arguments.
};
};
template<template<class>class Policy, typename ReturnType>
class execute :Policy<ReturnType>
{
public:
ReturnType res;
execute(ReturnType(*func)())
{res = Policy<ReturnType>().launch(func);}
};
template<typename ReturnType>
struct Policy1 {
ReturnType launch(ReturnType(*func)())
{/*some code*/
return func();}
};
template<typename ReturnType>
struct Policy2 {
ReturnType launch(ReturnType(*func)())
{/*some code*/
return func();}
};
template<template<class>class Policy, typename FunctorType>
auto createExecutor(const FunctorType& functor)
{
return execute<Policy, typename function_traits<FunctorType>::result_type(functor);
}
int main()
{
auto lambda_int = [] {return int(1); };
auto lambda_float = [] {return float(1.0); };
execute<Policy1, decltype(lambda_int())> exec1(lambda_int);
execute<Policy2, decltype(lambda_float())> exec2(lambda_float);
auto exec3 = createExecutor<Policy1>(lambda_float);
}
注意:我从用户 kennytm 那里获取了 function 特征助手: 是否有可能弄清楚 lambda 的参数类型和返回类型。 arguments 处理部分对于您的具体目的可能有点过分,可以进一步减少。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.