将基类中的继承构造函数与自定义构造函数混合

时间:2016-06-02 17:10:11

标签: c++ templates c++11

给出以下示例:

struct tag1 { };
struct tag2 { };

template<typename T>
class Base {
public:
  Base(T /*value*/) { }
  Base(tag1) { }
};

template<>
class Base<void> {
public:
  Base() { }
  Base(tag1) { }
};

template<typename T = void>
class MyClass : public Base<T> {
public:
  using Base<T>::Base;

  MyClass(tag2) : Base<T>(tag1{}) { }
};

int main() {
  {
    MyClass<> defaultConstructible;
    MyClass<> tagConstructible(tag2{});
  }
  {
    MyClass<int> valueConstructible(0);
    MyClass<int> tagConstructible(tag2{});
  }
}

MyClass可以使用任何类型进行参数化,当类型T等于void时,它应该是默认可构造的,否则它可以从类型T构造为写在main函数中。

我使用参数依赖的基类来获取此行为(通过使用基类的构造函数)。

此外,我还需要在接受其他参数的类层次结构中添加构造函数,如示例源(标记结构)中所示。

是否可以在不声明同一类中的所有构造函数的情况下执行此操作? 因为将超类构造函数与自定义构造函数混合将产生以下错误消息:

main.cpp: In function 'int main()':
main.cpp:30:15: error: no matching function for call to 'MyClass<>::MyClass()'
     MyClass<> defaultConstructible;
               ^~~~~~~~~~~~~~~~~~~~
main.cpp:22:18: note: candidate: MyClass<>::MyClass(tag1)
   using Base<T>::Base;
                  ^~~~
main.cpp:22:18: note:   candidate expects 1 argument, 0 provided
main.cpp:25:3: note: candidate: MyClass<T>::MyClass(tag2) [with T = void]
   MyClass(tag2) : Base<T>(tag1{}) { }
   ^~~~~~~
main.cpp:25:3: note:   candidate expects 1 argument, 0 provided
main.cpp:20:7: note: candidate: constexpr MyClass<>::MyClass(const MyClass<>&)
 class MyClass : public Base<T> {
       ^~~~~~~
main.cpp:20:7: note:   candidate expects 1 argument, 0 provided
main.cpp:20:7: note: candidate: constexpr MyClass<>::MyClass(MyClass<>&&)
main.cpp:20:7: note:   candidate expects 1 argument, 0 provided

Demo

2 个答案:

答案 0 :(得分:2)

一旦你引入了自己的构造函数,默认构造函数就不会被隐式定义 - 你尝试继承它并不重要。

您只需显式将默认构造函数定义为默认值:

template<typename T = void>
class MyClass : public Base<T> {
public:
  using Base<T>::Base;

  MyClass() = default;
  MyClass(tag2) : Base<T>(tag1{}) { }
};

此处,MyClass<>成为默认的可构造性,但MyClass<int>仍然不是因为Base<int>不是

答案 1 :(得分:0)

重申我的第一条评论:

  

一旦为MyClass引入参数化构造函数,编译器就不会生成默认构造函数

您可以轻松解决此问题,提供MyClass明确的默认构造函数:

template<typename T = void>
class MyClass : public Base<T> {
public:
  using Base<T>::Base;

  MyClass() = default; // <<<<<<<<<<<
  MyClass(tag2) : Base<T>(tag1{}) { }
};

Demo

Base<T>的默认行为不会被继承,但默认构造函数是使用= default;实现调用的。