繁体   English   中英

如何从 class 构造函数传递模板参数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM