给出以下示例:
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
答案 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{}) { }
};
Base<T>
的默认行为不会被继承,但默认构造函数是使用= default;
实现调用的。