英特尔C++编译器 (ICPC 14.0): "a derived class is not allowed here"

Intel C++ compiler (icpc 14.0): "a derived class is not allowed here"

本文关键字:derived class not here allowed is 编译器 C++ ICPC 英特尔      更新时间:2023-10-16

我在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

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

$ 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)

我找不到任何关于这个错误信息的有用信息。

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

void foo()
{
  A<1,true>::Nested<2>();
}

我仍然想现在如果ICC是正确的错误,或者这是否是一个编译器的错误。

谢谢你的时间!

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

template<int N>
struct A
{
  template<int M>
  struct Nested {};
};
template<int N>
struct B : public A<N> {};
template struct B<1>::Nested<2>;

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


BUG在icc

gccclang接受的代码段是合法的,不应该触发诊断。

负责icc内部发出提供的诊断的代码的作者可能绊倒了下面的代码片段,取自标准,它说依赖于模板参数Base中的名称不应该在Derived类的定义中可用。

14.6.2 依赖名称 [temp.dep]

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


如前所述,重要的是要注意[temp.dep]p3说在定义中不检查基类作用域,它并没有说从外部访问这些名称时不继承。

您的"工作"表明,名称(在本例中为template<int> struct Nested)确实(正确地)继承并在A<1, true>中可用,但icc似乎混淆了显式实例化与类

定义中的名称规则。