10

GCC が次のプログラムの呼び出しをあいまいと見なさないという事実に驚きました。foo()

#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);
}

上記の関数呼び出しはtrue、GCC 4.7.2 および GCC 4.8.0 (ベータ版) ではコンパイルされて返されますが、Clang 3.2 および ICC 13.0.1ではコンパイルされません(予想どおり)。

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

4

2 に答える 2

4

§7.3.3/3:

メンバー宣言として使用される using 宣言では、nested-name-specifier は、定義されているクラスの基本クラスに名前を付けるものとします。そのような using 宣言がコンストラクターに名前を付ける場合、nested-name-specifier は、定義されているクラスの直接の基本クラスに名前を付けます。それ以外の場合は、メンバー名のルックアップ (10.2, 3.4.3.1) で見つかった一連の宣言を導入します。

¶14:

… [ 注: 2 つの using 宣言は、同じ名前と同じパラメーター型を持つ関数を導入する場合があります。修飾されていない関数名の呼び出しに対して、関数オーバーロードの解決がそのような using 宣言によって導入された関数を選択する場合、関数呼び出しは不適切な形式です。

¶16:

オーバーロード解決のために、using 宣言によって派生クラスに導入された関数は、派生クラスのメンバーであるかのように扱われます。

したがって、using宣言は合法ですが、あなたが言ったように、関数は同じオーバーロード セット内のピアであり、プログラムの形式が正しくありません。

于 2013-02-26T03:41:42.593 に答える
1

foo(true)あなたが言うように、あなたのプログラムでの呼び出しは明らかに曖昧です。さらに、§10.2に示されているアルゴリズムによればあいまいであるため、使用時にフラグを立てる必要があります。(using宣言のフラグ付けは正しくありません。10.2(1)は、名前のあいまいな使用は、宣言ではなくルックアップでフラグが立てられることを明確に示しています。)

このプログラムを、認識されているgccバグの対象である同様のプログラムと対比するのは興味深いことです(並列をより明確にするために、そのバグレポートからわずかに変更されています)。

#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は問題なくコンパイルします。ただし、の2つのインスタンスのコメントを解除するとusing A::foo、どちらも変更されないfooため、gccはバグレポートに記載されている奇妙な重複エラーを生成します。using内部の2つの宣言のコメントを解除するCと、おそらくこの質問の対象である他のバグがトリガーされ、バグがマスクstatic functionされてプログラムが再度コンパイルされます。

clangは、このプログラムのすべての可能なバリアントを、その価値のために処理しているようです。

最後に、 (元のプログラムで)明示的に宣言foo(bool)されたものは、宣言によってスコープに持ち込まれたものよりも優先されることに注意してください。これらのバグは両方とも、各クラスのスコープ内のさまざまな関数宣言とそれらの個々の出所を(一連の宣言と関数宣言として)追跡しようとしているときの不正な簿記の結果であると思われます。Cfoo(bool)Cusingusing

于 2013-02-26T02:05:53.393 に答える