我把一些代码从MSVC(不允许)移植到linux,我了解到如果你在类的初始值列表中调用模板基类的构造函数,你必须指定所有的模板参数,否则就会出错。 似乎有点多余,因为如果您在重新键入模板参数时出错,那就是一个硬错误:
错误:键入“base<;int,true>;” 不是“派生”的直接基或虚拟基
此处为完整代码:
template <typename T, bool has_x>
struct Base
{
Base(T t): t_(t){
}
T t_=0;
};
template <typename T>
class Derived : public Base<T, false>
{
public:
// : Base<T, true> is hard error
Derived(const T& t) : Base<T, false>(t) {}
};
int main()
{
Derived d(47);
}
这是否有一个强有力的理由,或者只是标准化过程从来没有花时间来特例这个用例?
只有当derived
是模板并且基的类型取决于其模板参数时,您才需要这样做。
例如,这将编译:
template <typename T>
class Derived : public Base<int, false>
{
public:
Derived(const T& t) : Base(t) {}
};
据我所知,这里(在成员初始值设定项列表中)base
实际上是base<...>
的注入类名,像其他所有东西一样从它继承。
如果基的类型确实依赖于模板参数,那么它继承的注入类名就变得不可访问(至少是直接访问),就像从它继承的任何其他成员一样。
对于成员变量/函数,您可以添加this->
来访问它,但是对于类型成员,您需要derived::
:
template <typename T>
class Derived : public Base<T, false>
{
public:
Derived(const T& t) : Derived::Base(t) {}
};