7

我希望在英特尔编译器中使用一组用 C++ 编写的库。我附上了演示问题的示例代码。库中有很多地方使用了将“using”指令与部分重载结合使用(例如,我想使用基类中的 foo(void) 方法,但在派生类中重新实现第二个版本 fo foo) . gcc 没有问题,但 intel 有。

#include <iostream>
template <class F>
struct Interface
  {
     static const F f=10;
  };

template <class F>
struct Base : public Interface<F>
  {
     void foo (void) { std::cout << "void" << std::endl; }
     template <class FF>
     void foo (Interface<FF> &ii) { std::cout << "F : " << ii.f << std::endl; }
  };

template <class F,int i>
struct Derived : public Base<F>
  {
    // void foo (void) { Base<F>::foo(); }  // works fine
    using Base<F>::foo;                     // gives error
    template <class FF>
    void foo (Interface<FF> &ii) { std::cout << "Derived<" << i << "> F : " << ii.f << std::endl; }
 };

int main (void)
  {
    Derived<double,10> o;
    o.foo();                  // ok
    o.foo (o);                // problem
  }

icc 给出的编译器错误是:

test.cc(30): error: more than one instance of overloaded function "Derived<F, i>::foo    [with F=double, i=10]" matches the argument list:
        function template "void Base<F>::foo(Interface<FF> &) [with F=double]"
        function template "void Derived<F, i>::foo(Interface<FF> &) [with F=double, i=10]"
        argument types are: (Derived<double, 10>)
        object type is: Derived<double, 10>
o.foo (o);                // problem
  ^

compilation aborted for test.cc (code 2)

如果您删除该行

using Base<F>::foo;

并将其替换为行

void foo (void) { Base<F>::foo(); }

一切正常。

我的问题是有人知道这是一个特殊的 gcc 功能还是 icc 错误?或者是否有其他不涉及更改代码的工作?

这是 g++.real (Ubuntu 4.4.3-4ubuntu5) 4.4.3 和 icc (ICC) 12.0.2 20110112。

4

1 回答 1

5

对于 C++11,相关的标准引用可以在

7.3.3 using 声明 [namespace.udecl]

14/如果命名空间范围或块范围内的函数声明与 using 声明引入的函数具有相同的名称和相同的参数类型,并且声明没有声明相同的函数,则程序是非良构的。

这支持基于 EDG 的编译器。但是,一个特殊情况是用于类中的:

15/当 using-declaration 将基类中的名称带入派生类范围时,派生类中的成员函数和成员函数模板会覆盖和/或隐藏同名的成员函数和成员函数模板,parameter-type-list (8.3.5)、cv-qualification 和 ref-qualifier(如果有)在基类中(而不是冲突)。[ 注意:对于命名构造函数的 using 声明,请参见 12.9。—尾注] [示例:

struct B {
  virtual void f(int);
  virtual void f(char);
  void g(int);
  void h(int);
};

struct D : B {
  using B::f;
  void f(int); // OK: D::f(int) overrides B::f(int);

  using B::g;
  void g(char); // OK

  using B::h;
  void h(int); // OK: D::h(int) hides B::h(int)
};

void k(D* p)
{
  p->f(1); // calls D::f(int)
  p->f(’a’); // calls B::f(char)
  p->g(1); // calls B::g(int)
  p->g(’a’); // calls D::g(char)
}

—结束示例]

因此,在 C++11 中,Comeau 和 Intel 似乎是错误的。我不知道这些规则是否同样适用于 C++03

于 2011-10-04T09:53:11.953 回答