【问题标题】:Multiple parameter packs as factory function arguments多个参数包作为工厂函数参数
【发布时间】:2021-02-24 22:32:04
【问题描述】:

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

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

我研究过How can I have multiple parameter packs in a variadic template?;最高投票的答案只计算参数包中的参数,它不使用它们。我还查看了Multiple parameter packs — how?,这对于我的问题来说信息量不大,因为它传递了可变数量的相同类型的参数。

我现在在 std::make_tuple 处生成了关于无法转换为 tuple 的私有基类的错误。

如何将可变数量和类型的参数转发给工厂函数ProducerConsumer::create() 中的两个不同构造函数?另外,是否以及如何将右值引用应用于被转发的参数包?

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

【问题讨论】:

    标签: c++ templates variadic-templates parameter-pack


    【解决方案1】:

    两个问题:

    • 转发引用保留给T&amp;&amp;C&lt;T&amp;&amp;&gt; 不是转发引用。

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

    【讨论】:

    • 工作愉快!感谢您的回答并指出我 make_from_tuple()!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多