I'm using ICC 14.0.2 on Linux. This code snippet compiles with GCC and CLang, but not ICC:
template<int N, bool B>
struct A;
template<int N>
struct A<N,false>
{
template<int M>
struct Nested {};
};
template<int N>
struct A<N,true> : public A<N,false> {};
template struct A<1,true>::Nested<2>; // explicit instantiation
Trying to compile this with the three compilers:
$ g++ -c -std=c++11 testcase.cc
$ clang++ -c -std=c++11 testcase.cc
$ icpc -c -std=c++11 testcase.cc
testcase.cc(17): error: invalid qualifier for "A<1, false>::Nested<2>" (a derived class is not allowed here)
template struct A<1,true>::Nested<2>;
^
compilation aborted for testcase.cc (code 2)
I couldn't find any useful information about this error message.
In my case, the explicit instantiation (of more complicated classes) is part of a unit test, and I can work around the problem by instantiating an object instead, which ICC happily compiles:
void foo()
{
A<1,true>::Nested<2>();
}
Still I would like to now if ICC is right with its error or whether this is a compiler bug.
Thanks for your time!
Update Thank you Filip for the detailed analysis. I reported the issue to the Intel developers. Indeed the partial specialization has nothing to do with the problem (as I initially suspected), so even this simpler snippet reproduces the problem:
template<int N>
struct A
{
template<int M>
struct Nested {};
};
template<int N>
struct B : public A<N> {};
template struct B<1>::Nested<2>;
Note: gcc
and clang
are showing the correct behavior...
THE BUG IS IN icc
!
The snippet accepted by both gcc and clang is legal and should not trigger a diagnostic.
The author responsible for the code inside icc
that issues the provided diagnostic did probably trip over the below snippet, taken from the Standard, which says that names in a Base
that depends on a template-parameter should not be available inside the definition of the Derived
class.
14.6.2 Dependent Names
[temp.dep]
3In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.
As stated it is important to note that [temp.dep]p3
says that the base class scope is not examined in the definition of a class, it doesn't say that such names are not inherited when being accessed from the outside.
Your "work around" shows that the name (in this case template<int> struct Nested
) is indeed (correctly) inherited and available inside A<1, true>
, but icc
seems to confuse explicit instantiation with the rules of names inside the definition of the class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With