我有一个模板基类,它有一个构造函数,用于从该类的任何其他模板实例化转换,如下所示:
template <class T>
class FooBase
{
public:
FooBase()
{
}
template <class U>
FooBase(const FooBase<U>& other)
{
std::cout << "FooBase<U>" << std::endl;
}
};
注意没有定义复制构造函数。
然后我有一个派生模板类,它有一个复制构造函数,以及用于转换的构造函数:
template <class T>
class Foo : public FooBase<T>
{
public:
Foo()
{
}
Foo(const Foo& other) :
FooBase<T>(other)
{
}
template <class U>
Foo(const Foo<U>& other) :
FooBase<T>(other)
{
}
};
由于FooBase
没有复制构造函数,因此FooBase<T>(other)
会调用编译器生成的复制构造函数。这意味着如果我运行这个:
int main()
{
Foo<int> a;
Foo<int> b(a);
return 0;
}
输出为无,应为FooBase<U>
。
当然,我可以尝试通过在FooBase
中创建一个复制构造函数并使用delegating constructors来解决问题:
FooBase(const FooBase& other)
: FooBase<T>(other)
{
}
但不幸的是,它不起作用,并且会导致递归调用,因为编译器有用地指出:
warning C4717: 'FooBase<int>::FooBase<int>': recursive on all control paths, function will cause runtime stack overflow
因此唯一的解决方案是将逻辑复制到两个构造函数中。
有没有办法解决代码重复或单独的初始化函数?
答案 0 :(得分:4)
您可以拥有第三个私有构造函数,复制构造函数和构造函数模板都委托给它,并且包含实际工作:
template <typename T> class FooBase
{
struct Tag{};
template <typename U> // May have U = T
FooBase(Tag, const FooBase<U> & rhs)
{
// actual implementation
}
public:
FooBase(const FooBase & rhs) : FooBase(Tag(), rhs) {}
template <typename U> // Never selects U = T
FooBase(const FooBase<U> & rhs) : FooBase(Tag(), rhs) {}
};