为什么 C++ 要求我在初始化器列表中重复我的基类的模板参数?

NoS*_*tAl 3 c++ inheritance

我正在将一些代码从 MSVC(没有 permissive-)移植到 linux,我了解到如果在类的初始化列表中调用模板基类的构造函数,则必须指定所有模板参数,否则会出现错误。似乎有点多余,因为如果您在重新输入模板参数时犯了一个错误,那就是一个硬错误:

错误:类型 'Base<int, true>' 不是 'Derived' 的直接或虚拟基数

完整代码在这里:

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);
}
Run Code Online (Sandbox Code Playgroud)

这是否有充分的理由,或者只是标准化过程从未花时间处理这个用例的特殊情况?

Hol*_*Cat 8

您只需要在Derived模板时执行此操作,并且基的类型取决于其模板参数。

这编译,例如:

template <typename T>
class Derived : public Base<int, false>
{
public:
    Derived(const T& t) : Base(t) {}
};
Run Code Online (Sandbox Code Playgroud)

据我所知,这里(在成员初始值设定项列表中)Base实际上是 的注入类名Base<...>,像其他所有东西一样从它继承而来。

如果基类的类型确实依赖于模板参数,则其继承的注入类名将变得不可访问(至少直接不可访问),就像从它继承的任何其他成员一样。

对于成员变量/函数,您需要添加this->来访问它,但对于类型成员,您需要Derived::

template <typename T>
class Derived : public Base<T, false>
{
public:
    Derived(const T& t) : Derived::Base(t) {}
};
Run Code Online (Sandbox Code Playgroud)