简体   繁体   English

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

[英]How to pass template parameter from class constructor

I have template class and some Policies to use it.我有模板 class 和一些使用它的策略。 It just execute lambdas with specific policy.它只是执行具有特定策略的 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);
}

Client code work exactly what i need.客户端代码正是我需要的。 But i point to lambda twice and i wanna reduce class variable declaration in client code to this:但是我两次指向 lambda 并且我想将客户端代码中的 class 变量声明减少到此:

execute<Policy1> exec3(lambda_float);     

As i understand i cant use something like tempalte<auto ReturnType> because it works only with single argument.据我了解,我不能使用类似tempalte<auto ReturnType>的东西,因为它只适用于单个参数。 I also cannot use default parameter because i wanna pass any type of lambda return.我也不能使用默认参数,因为我想传递任何类型的 lambda 返回。

template<template<class>class Policy, typename ReturnType=int>
class execute :Policy<ReturnType>

The question is how to pass function return type, which is constructor args, to class template arguments?问题是如何将 function 返回类型(即构造函数参数)传递给 class 模板 arguments? Or may be there is another way?或者可能有另一种方式?

UPDATE: Based on Secundi answer.更新:基于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);
}

I do not know how much your sample code deviates from actual one, but if I take it at it's face value, I would reorganize it.我不知道您的示例代码与实际代码有多少偏差,但如果我从表面上看,我会重新组织它。

First observation I have is that your Policy doesn't have to be a template class.我的第一个观察是您的Policy不必是模板 class。 It does not have any members which need class-level template.它没有任何需要类级模板的成员。 Instead, the launch function can become a template:相反, launch function 可以成为模板:

struct Policy {
    template <class Callable>
    auto launch(Callable&& callable) {
     /*some code*/
     return callable();
    }
};

Now, there is no reason for your execute to inherit from Policy (this is also non-idiomatic for policy-type design).现在,您的execute没有理由从Policy继承(这对于策略类型设计来说也是非惯用的)。

We are still left with your lambda type deduction unsolved.我们还剩下你的 lambda 型扣未解决。 Ideally we would use class template argument deduction, and we can, Taking into account all that was said above, here is how I would change your execute :理想情况下,我们将使用 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;
};

And you would be able to use it like that:你可以这样使用它:

void foo()
{
    execute exec{Policy{}, [](){ return 10; }};
}

The standard says:标准说:

Class template argument deduction is only performed if no template argument list is present. Class 模板参数推导仅在不存在模板参数列表时执行。 If a template argument list is specified, deduction does not take place.如果指定了模板参数列表,则不会进行推导。

Therefore, you cannot achieve that this simple, although the functionality would make sense at first glance.因此,您无法做到这么简单,尽管乍一看该功能是有意义的。

A close solution via a function template helper that does not affect your current class design:通过不影响您当前 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);    
}

Note: I took the function traits helper from user kennytm: is it possible to figure out-the parameter type and return type of a lambda .注意:我从用户 kennytm 那里获取了 function 特征助手: 是否有可能弄清楚 lambda 的参数类型和返回类型 The arguments handling portion there might be overkill for your concrete purposes, can be reduced accordingly further on. arguments 处理部分对于您的具体目的可能有点过分,可以进一步减少。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 模板类专业化-如何将template参数传递给构造函数? - template class specialization - how to pass the template argument to constructor? 如何将类成员函数作为模板参数传递? - How to pass class member function as template parameter? 使用构造函数的类模板参数推断 - Class template parameter inference with constructor 如何使用构造函数(带参数)创建模板类,并将类的方法传递给线程 - How to create a template class with a constructor (with parameters) and pass a method of the class to a thread 如何在C ++中的另一个类main中传递类的构造函数参数 - how to pass a constructor parameter of a class in a different class main in C++ 从析构函数访问模板类构造函数的参数,可以吗? - Access to the template class constructor's parameter from the destructor, is it possible? 部分避免 class 模板参数(从构造函数参数推断) - Partially avoid class template parameter (deduce from constructor argument) 专门针对模板化模板参数的模板类构造函数 - Specialize template class constructor on templated template parameter 如何在没有基础模板参数的情况下将模板模板参数传递给模板类? - How to pass template template parameter to template class without the underlying template parameter? 如何从另一个类参数访问类构造函数参数 - How to access a class constructor parameter from the another class parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM