多个参数包作为工厂函数参数

Multiple parameter packs as factory function arguments

我正在尝试创建一个实例化模板 class 的工厂方法,方法是将组件 classes 的构造函数参数作为模板参数包传递。

ProducerConsumer 模板根据 ProducerConsumer 的类型参数化,它们由 ProducerConsumer 聚合。工厂函数的参数取决于参数化 classes.

的构造函数参数

我已经研究过 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. I've also looked ,这对我的问题没有任何帮助,因为它传递了数量可变的相同类型的参数。

我现在在 std::make_tuple 上生成关于无法投射到 tuple 的私人基地 class 的错误。

如何将可变数量和类型的参数转发给工厂函数中的两个不同构造函数,ProducerConsumer::create()?另外,是否以及如何将 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;
}

两期:

  • 转发引用保留给T&&C<T&&>不是转发引用。

  • tuple 变量不是可变参数变量,不能在其上使用 ...。在 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

并且由于您不使用可变参数,您可以将其简化为

    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