7

C++ で記述された一連のライブラリーを Intel コンパイラーで使用したいと考えています。問題を示すサンプル コードを添付しました。ライブラリには、'using' ディレクティブと部分的なオーバーロードを組み合わせて利用する場所がたくさんあります (たとえば、基本クラスから foo(void) メソッドを使用したいが、派生クラスで foo の 2 番目のバージョンを再実装したい)。 . 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 が名前を基本クラスから派生クラスのスコープに持ち込む場合、派生クラスのメンバー関数とメンバー関数テンプレートは、同じ名前のパラメーター型リストを持つメンバー関数とメンバー関数テンプレートをオーバーライドおよび/または非表示にします。 (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 に答える