[英]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.这里的问题是
Args1
和Args2
不是从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)...)
{}
};
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;
};
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.