可变模板和多重继承的组合
Combination of variadic templates and multiple inheritance
为了学习关于可变模板的一两件事,我偶然发现了这个(希望不是那么实际)问题。我有以下示例代码:
#include <utility>
#include <tuple>
#include <iostream>
template <typename... Args>
auto args(Args&&... args) {
return std::make_tuple(std::forward<Args>(args)...);
}
template <class C, class TupleArgs, std::size_t... Indices>
C construct_class_unpacked_(TupleArgs&& args, std::index_sequence<Indices...>) {
return C(std::get<Indices>(std::forward<TupleArgs>(args))...);
}
template <class C, typename TupleArgs>
C construct(TupleArgs&& args) {
return construct_class_unpacked_<C>(std::forward<TupleArgs>(args), std::make_index_sequence<std::tuple_size<typename std::decay<TupleArgs>::type>::value>());
}
struct Root {
Root(int l) : l_(l) {
}
protected:
Root() : l_(-2) {}
public:
int l_;
};
struct A : public virtual Root {
A(int i, float f) : i_(i), f_(f) {}
int i_;
float f_;
};
struct B : public virtual Root {
B(int j, float g) : j_(j), g_(g) {}
int j_;
float g_;
};
struct C : public virtual Root {
C() : x_(1), y_(3.1) {
}
int x_;
float y_;
};
template <typename Base, typename... Bases>
struct S : public Bases... {
template <typename Arg, typename... TupleArgs>
S(Arg&& arg, TupleArgs&&... args) : Base(std::forward<Arg>(arg)), Bases(construct<Bases>(std::forward<TupleArgs>(args)))... {
}
};
int main (int argc, char const* argv[]) {
{
S<Root, A, C, B> s(4, args(2, 3.1f), args(), args(3, 5.3f));
std::cout << s.i_ << "n";
std::cout << s.f_ << "n";
std::cout << s.j_ << "n";
std::cout << s.g_ << "n";
std::cout << s.x_ << "n";
std::cout << s.y_ << "n";
std::cout << s.l_ << "n";
}
}
这里最初的问题是:如何将构造函数参数传递给多个基类。仅仅使用可变模板参数就会限制每个基类只能有一个参数。然而,如果我想为每个基类设置可变数量的参数,我能想到的最聪明的方法就是使用"旧的"元组方法。
显然,这个"解决方案"有一个警告,即A,B,C中间类被构造并移动/复制,因此每次分别调用根构造函数。使用具有固定基类计数的真正基类构造函数将导致Root::Root只被调用一次(好吧,仍然存在菱形问题…)。
我的问题是:你有什么办法更优雅地解决这个问题吗(除了避免可变多重继承的明显解决方案之外)
请记住,这个问题更多的是学术性的,所以"为什么不告诉我们你想解决什么真正的问题?"这样的问题是毫无意义的。
您可以使用一个助手类来执行单个基的初始化。(它不是我最初所说的包装器;它不使用聚合,而是使用继承。)
template<class Tuple>
auto make_index_sequence_for_tuple_expansion(Tuple&&)
{
using decayed_tuple = typename std::decay<Tuple>::type;
return std::make_index_sequence<std::tuple_size<decayed_tuple>::value>();
}
template<class T>
struct unpacker : T
{
template<class Tuple, std::size_t... Is>
unpacker(Tuple&& tuple, std::index_sequence<Is...>)
: T( std::get<Is>(std::forward<Tuple>(tuple))... )
{}
template<class Tuple>
unpacker(Tuple&& tuple)
: unpacker( std::forward<Tuple>(tuple),
make_index_sequence_for_tuple_expansion(tuple) )
{}
};
template <typename Base, typename... Bases>
struct S : public unpacker<Bases>... {
template <typename Arg, typename... TupleArgs>
S(Arg&& arg, TupleArgs&&... args)
: Base(std::forward<Arg>(arg))
, unpacker<Bases>(std::forward<TupleArgs>(args))...
{}
};
生活例子
相关文章:
- 关于C++中具有多重继承"this"指针的说明
- C++中模板化异常类的多重继承
- 虚拟继承中是否存在多重继承?
- 如何在 c++ 多重继承中调用父非虚函数?
- 多重继承相同的方法名,没有歧义
- 使用enable_if解决多重继承歧义
- 多重继承导致虚假的模糊虚拟函数过载
- 多重继承和访问不明确的元素
- C++ 多重继承:使用基类 A 的实现实现基类 B 的抽象方法
- 多重继承中的派生类的行为类似于聚合
- 为什么我的 Hippomock 期望在使用多重继承时失败
- 带有此指针的模板类多重继承构造函数不起作用?
- 使用多重继承时出现编译错误
- 增强多重继承的序列化
- 多重继承:跳过'virtual'关键字并拒绝菱形层次结构的使用?
- 仅函数的多重继承 - 没有虚拟和 CRTP
- C++多重继承和鸭子类型
- C++两次从文件保存对象读取多重继承
- 如何在 c++ 中将多重继承与组合一起使用?
- 可变模板和多重继承的组合