C++,将两个参数包传递给构造函数

C++, pass two parameter packs to constructor

我有以下问题。我有一个 class (mixin),它有两个模板库。

template <typename T>
class Id
{
    using result = T;
};

template <typename Printer1, typename Printer2>
class SeveralPrinters : public Printer1, public Printer2
{
    template <typename... Args1, typename... Args2>
    SeveralPrinters(dummy, helper<Args1...>, helper<Args2...>,
                    typename Id<Args1>::result... args1,
                    typename Id<Args2>::result... args2)
        : Printer1(std::forward<Args1>(args1)..., std::forward<Args2>(args2)...)
    {}
public:
    template <typename... Args, typename = 
std::enable_if_t<!contains<dummy, Args...>::result>>
    SeveralPrinters(Args&&... args)
        : SeveralPrinters(dummy(), typename Printer1::ArgsCtor(), 
typename Printer2::ArgsCtor(), std::forward<Args>(args)...)
    {
    }
};

class所有姓名均为虚构。所以,假设它的第一个基数接受 int 作为构造函数参数,第二个基数接受 double。我想要做的是能够像 SeveralPrinters(1, 2.) 一样调用 SeveralPrinters 的构造函数。这里的问题是 Args1Args2 不是从 helper 结构推导出来的,而是从 args 推导出来的,在辅助结构之后传递。如您所见,我尝试将模板参数包装到 Id 结构中,但这没有帮助。我知道,它被称为 Non-deduced contexts 之类的东西,但我无法让它发挥作用。任何人都可以帮助它(如果可能的话),并且可以解释一下这个主题(为什么它现在不起作用)。 基数 classes 的示例:

class BasicPrinter1
{
public:
    BasicPrinter1(int)
    {}
    void f()
    {
    }
    using ArgsCtor = helper<int>;
};

class BasicPrinter2
{
public:
    BasicPrinter2(int*)
    {}
    void g()
    {
    }
    using ArgsCtor = helper<int*>;
};

它不起作用主要是因为 Id 中的别名 resultprivate(类 的默认可访问性),所以无法从 SeveralPrinters 的私有构造函数访问,导致替换失败 (typename Id<Args1>::result),没有其他可行的候选构造函数可以调用。您的代码中还有一些拼写错误。

template <typename T>
struct Id
{
    using result = T;
};

template <typename Printer1, typename Printer2>
class SeveralPrinters : public Printer1, public Printer2
{
    template <typename... Args1, typename... Args2>
    SeveralPrinters(dummy, helper<Args1...>, helper<Args2...>
                  , typename Id<Args1>::result... args1
                  , typename Id<Args2>::result... args2)
        : Printer1(std::forward<Args1>(args1)...)
        , Printer2(std::forward<Args2>(args2)...)
    {}

public:    
    template <typename... Args>
    SeveralPrinters(Args&&... args)
        : SeveralPrinters(dummy{}
                        , typename Printer1::ArgsCtor{}
                        , typename Printer2::ArgsCtor{}
                        , std::forward<Args>(args)...)
    {}
};

DEMO


为了将参数完美转发到基 类,您应该改为声明参数数量 (ArgsCount) 并使用以下实现:

template <typename Printer1, typename Printer2>
class SeveralPrinters : public Printer1, public Printer2
{
    template <std::size_t... Is
            , std::size_t... Js
            , typename... Args>
    SeveralPrinters(std::index_sequence<Is...>
                  , std::index_sequence<Js...>
                  , std::tuple<Args...>&& t)
        : Printer1(std::get<Is>(std::move(t))...)
        , Printer2(std::get<sizeof...(Is) + Js>(std::move(t))...)
    {}

public:
    SeveralPrinters() = default;
    SeveralPrinters(const SeveralPrinters&) = default;
    SeveralPrinters(SeveralPrinters& rhs)
        : SeveralPrinters(static_cast<const SeveralPrinters&>(rhs))
    {}

    template <typename... Args>
    SeveralPrinters(Args&&... args)
        : SeveralPrinters(std::make_index_sequence<Printer1::ArgsCount>{}
                        , std::make_index_sequence<Printer2::ArgsCount>{}
                        , std::forward_as_tuple(std::forward<Args>(args)...))
    {}
};

struct BasicPrinter1
{
    BasicPrinter1(int) {}
    static constexpr ArgsCount = 1;
};

struct BasicPrinter2
{
    BasicPrinter2(int*, char&) {}
    static constexpr ArgsCount = 2;
};

DEMO 2

另请注意我是如何保护复制构造函数不被转发引用构造函数掩盖的。