如何按照标准实例化包含嵌套子class模板的class模板

How to instantiate, by the standard, a class template containing nested subclass templates

有模板声明

template<class C> struct Data {
    template<typename T> struct Item1 {
        void Test() {
        }
    };
};

使用带有编译选项 /std:c++latest 的 MSVC v19.28,我尝试按如下方式实例化模板:

template<class C> struct Data {
    template<typename T> struct Item1 {
        void Test() {
        }
    };
};

template <class C> struct MyData : Data<C> {
    MyData::Item1<int> item10;              // (1)
};

struct S;

MyData<S> dataS;

代码已使用 MSVC 成功编译(参见 link), but gcc 11.1 and clang 12.0.0 could not compile it (links for gcc and clang

我尝试使用不同的声明实例化模板

template <class C> struct MyData : Data<C> {
    MyData::Item1<int> item10;              // (1)
    Data<C>::Item1<int> item11;             // (2)
    Data<C>::template Item1<int> item12;    // (3)
};

MSVC 编译所有这些,但 gcc 和 clang 不编译。

我“找到”了一个 solution,它“适用于”所有提到的编译器

template<typename C, typename T> struct Item2 {
    void Test() {
    }
};

template<class C> struct Data {
};

template <class C> struct MyData : Data<C> {
    Item2<C, int> item20;
};

struct S;

MyData<S> dataS;

它使用独立模板。

如何声明原始模板实例化符合C++标准? MSVC 编译了所有 3 个选项,这是它的缺陷吗?

这里有一些问题:

template <class C> struct MyData : Data<C> {
  MyData::Item1<int> item10;
};

MyData 在这里是一个不完整的类型,所以我们还不能那样使用它。但是,由于Item1继承自Data<C>,我们应该可以直接引用它:

Data<C>::Item1<int> item10;

但是现在,Data<C>::Item1是一个依赖类型,所以我们需要使用typename来告诉编译器它实际上是一个类型:

typename Data<C>::Item1<int> item10;

最后,因为Item1是依赖类型的模板成员,我们需要告诉编译器它是一个模板(相对于常量或其他东西)。

typename Data<C>::Item1 template<int> item10;

最后,我们降落在:

template<class C> struct Data {
    template<typename T> struct Item1 {
        void Test() {
        }
    };
};

template <class C> 
struct MyData : Data<C> {
    typename Data<C>::template Item1<int> item10;
};

struct S;

MyData<S> dataS;