Question

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>;
Was it helpful?

Solution

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]

3 In 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top