在模板化类中构造对象所需的异常初始化

问题描述

我有一些结构如下的代码

enum class Type {a,b,c,d};


template<typename T>
class External {
    public:
        External(Type t) {

        }
};


template<typename T>
class Base {};

template<typename T>
class Derived : Base<T> {
    public:
    private:
        External<int> e(Type::a);
};


int main() {
    Derived<int> der;

    return 0;
}

使用 g++ 编译时,会出现以下错误

<source>:49:25: error: 'Type::a' is not a type
   49 |         External<int> e(Type::a);
      |                         ^~~~

通过一些实验,我发现如果我以不同的方式构造 External 类型的对象,它会起作用:

template<typename T>
class Derived : Base<T> {
    public:
    private:
        External<int> e = External<int>(Type::a);
};

为什么会这样?为什么编译器在第一种情况下需要一个类型?

解决方法

编译器试图将 e 解释为成员函数,因此它试图将 Type::a 视为一种类型。

对于 default member initializer,您只能使用花括号初始化列表或等号初始值设定项(如您所示)。

通过一个默认成员初始值设定项,它是包含在成员声明中的大括号或等号初始值设定项,并且在构造函数的成员初始值设定项列表中省略该成员时使用。

template<typename T>
class Derived : Base<T> {
    public:
    private:
        External<int> e{Type::a};
};