2

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

模板根据和ProducerConsumer的类型进行参数化,这些类型由聚合。工厂函数的参数取决于参数化类的构造函数参数。ProducerConsumerProducerConsumer

我研究过如何在可变参数模板中有多个参数包?; 投票最高的答案只计算参数包中的参数,它不使用它们。我还查看了多个参数包——如何?,这对我的问题来说是相当无信息的,因为它传递了可变数量的相同类型的参数。

我现在所拥有的std::make_tuple关于无法转换为tuple私有基类的错误。

如何将可变数量和类型的参数转发给工厂函数中的两个不同构造函数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;
}
4

1 回答 1

2

两个问题:

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

  • 元组变量不是可变参数,你不能...在它上面使用。在 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);
}

演示

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

    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);
    }

演示

于 2020-11-12T22:01:55.987 回答