英特尔C++编译器(icpc 14.0):"这里不允许派生类"

PiQ*_*uer 7 c++ compiler-errors icc language-lawyer

我在Linux上使用ICC 14.0.2.此代码段与GCC和CLang编译,但不编译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
Run Code Online (Sandbox Code Playgroud)

尝试用三个编译器编译它:

$ 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)
Run Code Online (Sandbox Code Playgroud)

我找不到有关此错误消息的任何有用信息.

在我的例子中,显式实例化(更复杂的类)是单元测试的一部分,我可以通过实例化一个对象来解决问题,ICC愉快地编译:

void foo()
{
  A<1,true>::Nested<2>();
}
Run Code Online (Sandbox Code Playgroud)

如果ICC对它的错误或者这是否是编译器错误,我现在仍然想.

谢谢你的时间!

更新 谢谢Filip的详细分析.向英特尔开发人员报告了这个问题.事实上,部分专业化与问题无关(正如我最初所怀疑的那样),所以即使这个更简单的片段也会重现问题:

template<int N>
struct A
{
  template<int M>
  struct Nested {};
};

template<int N>
struct B : public A<N> {};

template struct B<1>::Nested<2>;
Run Code Online (Sandbox Code Playgroud)

Fil*_*efp 7

注意: gccclang显示正确的行为......


BUG进来了icc!

gccclang接受的片段是合法的,不应触发诊断.


负责icc发布所提供诊断的内部代码的作者可能会跳过下面的片段,取自标准,该片段Base表示依赖于模板参数的名称不应该在Derived类的定义中可用.

14.6.2 从属名称 [temp.dep]

3 在类或类模板的定义中,如果基类依赖于 模板参数,则在类模板或成员的定义点或实例化期间,不会在非限定名称查找期间检查基类作用域.类模板或成员.


如上所述,重要的是要注意,[temp.dep]p3类的定义中没有检查基类范围,它并不表示从外部访问时不会继承这些名称.

你的"解决方法"表明名称(在这种情况下template<int> struct Nested)确实(正确地)继承并在内部可用A<1, true>,但icc似乎混淆了显式实例化类定义中的名称规则.

  • 它可能来自`icc`的特定开发人员;) (2认同)