从参数包中的base继承构造函数

时间:2015-09-06 10:10:25

标签: c++11 inheritance constructor multiple-inheritance variadic-templates

在C ++ 11中,可以“继承构造函数”:

struct A{  };

struct B : A{
  using A::A;
};

在某些情况下(参见下面的讨论),也可以使用多个继承构造函数。

struct D : A, B, C{
  using A::A;
  using B::B;
  using C::C;
};

最后,还可以从参数包中的所有类型继承:

template<class... Ts>
struct D2 : Ts...{};

问题:是否可以一般性地继承基类的所有构造函数?像这样:

template<class... Ts>
struct D2 : Ts...{
   using Ts::Ts...; // ??? compiler error 
};

这样struct D2<A, B, C>与上面的struct D等效。

2 个答案:

答案 0 :(得分:2)

通常(不太漂亮)的解决方法是递归:

template<class... Ts>
struct D { };

template<class T, class... Ts>
struct D<T, Ts...>: T, D<Ts...>{
  using D<Ts...>::D;
  using T::T;
};

Demo

请注意,在当前继承构造函数的规范下,这并不完全等同于

struct D : A, B, C{
  using A::A;
  using B::B;
  using C::C;
};

版本,如果按值传递构造函数参数可能效率低,因为继承构造函数调用链需要多次移动(可能会退化为传统类型的副本)。 Demo

论文N4429解决了这个以及与继承构造函数相关的其他一些问题,并已通过Lenexa的EWG审核。

答案 1 :(得分:0)

不,这样的事情是不可能的。有list of contexts允许发生包扩展, using-declaration 不是其中之一。

mem-initializer-list 是一个允许的上下文,所以你可以这样做:

struct A { A(int ) { } };
struct B { B(int ) { } };

template <typename... Ts >
struct D : Ts... {
    template <typename... Args>
    D(Args&&... args) : Ts(std::forward<Args>(args)...)... { }
};

int main() {
    D<A, B> d(4);
}

上面实际上无法在gcc 5.2中编译(bug 65422)。