简体   繁体   English

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

[英]C++, pass two parameter packs to constructor

I have the following problem.我有以下问题。 I have a class ( mixin ), that has two template bases.我有一个类( 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)...)
    {
    }
};

All names of classes are fictitious.所有类的名称都是虚构的。 So, imagine its first base accepts int as constructor argument and second base accepts double .所以,想象一下它的第一个基数接受int作为构造函数参数,第二个基数接受double What I want to do is to be able to call constructor of SeveralPrinters like SeveralPrinters(1, 2.) .我想要做的是能够像SeveralPrinters(1, 2.)一样调用SeveralPrinters构造函数。 The problem here, is that Args1 and Args2 are deduced not from helper structure, but from args, passed after helper structure.这里的问题是Args1Args2不是从helper结构推导出来的,而是从辅助结构之后传递的 args 推导出来的。 As you can see, I tried to wrap template arguments into Id structure, and that didn't help.如您所见,我尝试将模板参数包装到Id结构中,但这没有帮助。 I know, it is called smth like Non-deduced contexts , but I couldn't manage to make it work.我知道,它被称为 smth like Non-deduced contexts ,但我无法让它工作。 Can anyone help with it (if it possible), and maybe explain a little bit more on this topic (why it doesn't work now).任何人都可以提供帮助(如果可能的话),并且可能会就此主题进行更多解释(为什么它现在不起作用)。 Example of base classes:基类示例:

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

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

It doesn't work mainly because the alias result in Id is private (default accessibility for classes), and so not accessible from the private constructor of SeveralPrinters , leading to a substitution failure ( typename Id<Args1>::result ) with no other viable candidate constructor to call.它不起作用主要是因为Id的别名result私有的(类的默认可访问性),因此无法从SeveralPrinters的私有构造函数SeveralPrinters ,导致替换失败( typename Id<Args1>::result )而没有其他要调用的可行候选构造函数。 There were also a couple of typos in your code.您的代码中还有一些拼写错误。

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演示


In order to perfectly-forward the arguments to base classes, you should instead declare the number of parameters ( ArgsCount ) and use the below implementation:为了完美地将参数转发给基类,您应该声明参数的数量( 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演示 2

Also notice how I'm protecting the copy-constructor from being overshadowed by the forwarding-references constructor.还要注意我是如何保护复制构造函数不被转发引用构造函数所掩盖的。

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

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