Объединение директивы using с частичной перегрузкой: функция gcc или ошибка intel? - PullRequest
7 голосов
/ 04 октября 2011

Я хочу использовать набор библиотек, написанных на C ++, с компиляторами Intel.Я приложил пример кода, который демонстрирует проблему.В библиотеках есть много мест, где они используют объединение директивы 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.

1 Ответ

5 голосов
/ 04 октября 2011

Для C ++ 11 соответствующее стандартное предложение можно найти в

7.3.3 Объявление использования [namespace.udecl]

14 / Если объявление функции в области пространства имен или области блока имеет то же имя и тот же тип параметров, что и функция, представленная в объявлении использования, и объявления не объявляют одну и ту же функцию, программа некорректна.

Это поддерживает компиляторы на основе EDG. Однако для использования в классах предназначен особый случай:

15 / Когда объявление использования переносит имена из базового класса в область производного класса, функции-члены и шаблоны функций-членов в производном классе переопределяют и / или скрывают функции-члены и шаблоны функций-членов с помощью то же имя, список параметров-типов (8.3.5), квалификация cv и квалификатор ref (если есть) в базовом классе (а не конфликтующий). [Примечание: для объявлений об использовании, которые называют конструктор, см. 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

...