2013-02-26 6 views
9

にコンパイルエラーが発生することはありません。私は、GCCががあいまい次のプログラムでfoo()への呼び出しを検討していないという事実に驚いた:上記の関数呼び出しがコンパイル明らかにあいまいな呼び出しは、GCC

#include <iostream> 

struct B1 { bool foo(bool) { return true; } }; 
struct B2 { bool foo(bool) { return false; } }; 

struct C : public B1, public B2 
{ 
    using B1::foo; 
    using B2::foo; 
}; 

int main() 
{ 
    C c; 

    // Compiles and prints `true` on GCC 4.7.2 and GCC 4.8.0 (beta); 
    // does not compile on Clang 3.2 and ICC 13.0.1; 
    std::cout << std::boolalpha << c.foo(true); 
} 

をし、 GCC 4.7.2とGCC 4.8.0(ベータ版)にtrueを返しますが、はClang 3.2とICC 13.0.1で(私が期待していた通りです)をコンパイルしません。

これは「診断不要」 "のケースですか、それともGCCのバグですか? C++ 11標準への参照が推奨されています。

+0

VC11でビルドに失敗しました。あいまいな呼び出しエラー。 –

+0

@MarkGarcia:はい、それはGCCだけが受け入れるようです。問題は、これがバグに起因するのか、この種のエラーに診断が必要ないのかです。 –

+0

FWIW、g ++ 4.4.3では、 'main'で' foo'を使うのではなく、 'C'で' using'ですでにエラーが出ています: 'ambig.cc:9:error:using using 'B2 :: foo 'は以前の宣言を使って競合する ' – us2012

答えて

4

§7.3.3/ 3:

In a using-declaration used as a member-declaration, the nested-name-specifier shall name a base class of the class being defined. If such a using-declaration names a constructor, the nested-name-specifier shall name a direct base class of the class being defined; otherwise it introduces the set of declarations found by member name lookup (10.2, 3.4.3.1).

¶14:

… [ Note: Two using-declarations may introduce functions with the same name and the same parameter types. If, for a call to an unqualified function name, function overload resolution selects the functions introduced by such using-declarations, the function call is ill-formed.

¶16:だから

For the purpose of overload resolution, the functions which are introduced by a using-declaration into a derived class will be treated as though they were members of the derived class.

using宣言は法的ですが、機能がありますあなたが言ったように、同じオーバーロードセットの同輩たちは、プログラムがうまく構成されていません。

1

あなたのプログラムでfoo(true)への呼び出しは、あなたの言うとおり、明確にあいまいです。さらに、§ 10.2に示されているアルゴリズムではあいまいであるため、使用時にフラグを立てる必要があります。 (usingの宣言にフラグを立てると間違っています; 10.2(1)は、宣言ではなくルックアップでフラグが付けられていることを明示しています)。

このプログラムと似ているのは、 a recognized gcc bugは(わずかに平行をより明確にするために、そのバグレポートから変更):

#include <iostream> 

struct A { 
    static int foo() {return 1;} 
    static int foo(char) { return 2;} 
}; 

struct B1 : A { 
// using A::foo; 
}; 
struct B2 : A { 
// using A::foo; 
}; 

struct C : B1, B2 { 
// using B1::foo; 
// using B2::foo; 
}; 

int main() 
{ 
    std::cout << C::foo(); 
} 

上記プログラムは正しいです。ダイヤモンドの継承にもかかわらず、fooは固定メンバーでAなので、あいまいではありません。実際、gccは問題なくコンパイルします。しかし、fooのいずれも変更されないusing A::fooの2つのインスタンスのコメントを外すと、gccはバグレポートに記載されている奇妙な重複エラーを引き起こします。 C内の2つのusing宣言のコメントを外します。この疑問の対象となる他のバグがおそらくトリガーされ、static functionのバグがマスクされ、プログラムが再びコンパイルされます。

clangは、このプログラムのすべての可能な変形を、それが価値があるものとして扱うようです。

は最後に、using宣言によってCの範囲に持ち込ま任意のfoo(bool)をかけて勝つ明示的に(オリジナルのプログラムで)Cfoo(bool)を宣言したことに注意してください。私は、これらのバグの両方が、各クラスのスコープと個々の起点(さまざまな宣言と関数宣言のシーケンスとして)のさまざまな関数宣言を追跡しようとしている間に悪い簿記の結果であると思われます。

関連する問題