简体   繁体   English

多个参数包为出厂 function arguments

[英]Multiple parameter packs as factory function arguments

I am trying to create a factory method that instantiates a template class by passing the constructor arguments for the component classes as template parameter packs.我正在尝试创建一个工厂方法,通过将组件类的构造函数 arguments 作为模板参数包传递来实例化模板 class。

The ProducerConsumer template is parameterized on the types of the Producer and Consumer , which are aggregated by ProducerConsumer . ProducerConsumer模板根据ProducerConsumer的类型进行参数化,这些类型由ProducerConsumer聚合。 Arguments to the factory function depend on the constructor arguments of the parameterizing classes. Arguments 到工厂 function 取决于参数化类的构造函数 arguments。

I've studied How can I have multiple parameter packs in a variadic template?我研究过如何在可变参数模板中包含多个参数包? ; ; the highest voted answer only counts the arguments in the parameter pack, it does not use them.投票最高的答案只计算参数包中的 arguments,它不使用它们。 I've also looked Multiple parameter packs — how?我还查看了多个参数包——怎么样? , which is rather uninformative for my problem as it passes a variable number of arguments of the same type. ,这对我的问题来说是相当无用的,因为它传递了相同类型的变量 arguments。

What I have now generates errors at the std::make_tuple about not being able to cast to tuple 's private base class.我现在所拥有的在std::make_tuple中生成关于无法转换为tuple的私有基数 class 的错误。

How do I forward a variable number and types of arguments to two different constructors within the factory function, ProducerConsumer::create() ?如何将可变数量和类型 arguments 转发给工厂 function, ProducerConsumer::create()中的两个不同构造函数? Also, if and how should r-value reference be applied to the parameter packs being forwarded?此外,是否以及如何将 r 值引用应用于正在转发的参数包?

#include <iostream>
#include <tuple>
#include <chrono>


using Duration = std::chrono::steady_clock::duration;


struct ProducerBase {
    ProducerBase(Duration maxWait) 
        : maxWait_{ maxWait }
    {}
    Duration maxWait_;
};

struct ConsumerBase {
    ConsumerBase(int capacity, Duration maxWait) :
        capacity_{ capacity },
        maxWait_{ maxWait }
    {}
    int capacity_;
    Duration maxWait_;
};


template <typename Producer, typename Consumer>
struct ProducerConsumer {
    
    template < typename ... ProducerArgs, typename ... ConsumerArgs >
        static ProducerConsumer* create(
            std::tuple<ProducerArgs&& ...> producerArgs,
            std::tuple<ConsumerArgs&& ...> consumerArgs
        )
    {
        auto producer = new Producer(std::forward<ProducerArgs>(producerArgs)...);
        auto consumer = new Consumer(std::forward<ConsumerArgs>(consumerArgs)...);
        return new ProducerConsumer<Producer, Consumer>(producer, consumer);
    }

    ProducerConsumer(ProducerBase* producer, ConsumerBase* consumer)
        :
        producer_{ producer },
        consumer_{ consumer }
    {}

    ProducerBase* producer_;
    ConsumerBase* consumer_;
};

using namespace std::chrono_literals;

int main(int argc, char* argv[]) {
    Duration const MaxWait{ 10s };
    int const Capacity{ 32 };
    using PC = ProducerConsumer<ProducerBase, ConsumerBase>;
    auto pc = PC::create(std::make_tuple(MaxWait), std::make_tuple(Capacity, MaxWait));
    return 0;
}

Two issues:两个问题:

  • forwarding reference is reserved to T&& , C<T&&> is not forwarding reference.转发引用保留给T&&C<T&&>不是转发引用。

  • tuple variable is not a variadic variable, you cannot use ... on it. tuple 变量不是可变参数变量,您不能在其上使用... in C++17, there isstd::make_from_tuple to do what you want:在 C++17 中,有std::make_from_tuple可以做你想做的事:

template < typename ... ProducerArgs, typename ... ConsumerArgs >
    static ProducerConsumer* create(
        std::tuple<ProducerArgs...> producerArgs,
        std::tuple<ConsumerArgs...> consumerArgs
    )
{
    auto producer = new Producer(std::make_from_tuple<Producer>(producerArgs));
    auto consumer = new Consumer(std::make_from_tuple<Consumer>(consumerArgs));
    return new ProducerConsumer<Producer, Consumer>(producer, consumer);
}

Demo演示

And as you don't use variadic, you might simplify it to由于您不使用可变参数,因此您可以将其简化为

    template < typename ProducerTupleArgs, typename ConsumerTupleArgs >
        static ProducerConsumer* create(
            ProducerTupleArgs&& producerArgs,
            ConsumerTupleArgs&& consumerArgs
        )
    {
        auto producer = new Producer(std::make_from_tuple<Producer>(std::forward<ProducerTupleArgs>(producerArgs)));
        auto consumer = new Consumer(std::make_from_tuple<Consumer>(std::forward<ConsumerTupleArgs>(consumerArgs)));
        return new ProducerConsumer<Producer, Consumer>(producer, consumer);
    }

Demo演示

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

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