Reputation: 8660
There is a template declaration
template<class C> struct Data {
template<typename T> struct Item1 {
void Test() {
}
};
};
Using MSVC v19.28 with the compile option /std:c++latest, I tried to instantiate the template as follows:
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;
The code was compiled successfully with MSVC (see the link), but gcc 11.1 and clang 12.0.0 could not compile it (links for gcc and clang)
I tried to instantiate the template using different declarations
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 compiles all of them, but gcc and clang do not.
I have "found" a solution, which "works" with all the mentioned compilers
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;
It uses a stand-alone template.
How to declare the original template instantiation to conform to the C ++ standard? The fact that MSVC compiles all 3 options, is a flaw of it?
Upvotes: 1
Views: 153
Reputation:
There's a few things going wrong here:
template <class C> struct MyData : Data<C> {
MyData::Item1<int> item10;
};
MyData
is an incomplete type here, so we can't use it just yet in that way. However, since Item1
is inherited from Data<C>
, we should be able to just refer to it directly:
Data<C>::Item1<int> item10;
But now, Data<C>::Item1
is a dependant type, so we need to use typename
to tell the compiler that it is, in fact, a type:
typename Data<C>::Item1<int> item10;
Finally, because Item1
is a template member of a dependant type, we also need to tell the compiler that it is a template (as opposed to a constant or something).
typename Data<C>::Item1 template<int> item10;
So at the end, we land at:
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;
Upvotes: 4