5

まず、問題を示す小さな例:

struct Bar {
    enum Baz {aa, bb, cc};
    Baz baz_;

    operator Baz() const { return baz_; }
    private:
        template<typename T> operator T() const;
};

int main() {
    Bar bar;
    switch (bar) {
        case Bar::aa:
            break;
        case Bar::bb:
            break;
        case Bar::cc:
            break;
        default:
            break;
    }
    return 0;
}

このコードをg++4.7.0でコンパイルすると、次のエラーが発生します。

foo.cpp: In function ‘int main()’:
foo.cpp:12:16: error: ambiguous default type conversion from ‘Bar’
foo.cpp:12:16: error:   candidate conversions include ‘template<class T> Bar::operator T() const’

私の理解では、構造体オブジェクトが「スイッチオン」されているため、コンパイラは整数型または列挙型への変換関数を見つけようとします。Bar :: Baz列挙型にパブリック変換関数を明示的に提供し、それを使用したいと思います。

私にとって紛らわしいのは、コンパイラーもプライベート変換関数を見つけて、どちらを使用するかを決定できないことです。なぜ私的な​​機能を考慮しているのですか?たとえば、明示的なキャストを追加するとswitch((int)bar)、プライベート変換関数のみが一致し、コンパイラは、プライベートであるため使用できないと正しく文句を言います。では、このコンテキストではプライベート変換関数を使用できないので、なぜ2つのどちらを選択するのかが明確ではないのでしょうか。

興味深いことに、このコードはg ++ 4.6でエラーなしでコンパイルされると思います(100%確実ではありませんが)。

編集:コメントでJames McNellisが指摘しているように、プライベート変換関数がテンプレート化されているという事実もここに関連しています。

4

2 に答える 2

3

アクセス制御は、過負荷の解決後に行われます。これは、標準§13.3で指定されています

過負荷解決は、呼び出しの引数となる式のリストと、呼び出しのコンテキストに基づいて呼び出すことができる候補関数のセットを指定して、呼び出すのに最適な関数を選択するためのメカニズムです。最適な関数の選択基準は、引数の数、引数が候補関数のパラメーターのタイプとどの程度一致するか、オブジェクトが暗黙のオブジェクトパラメーターとどの程度一致するか(非静的メンバー関数の場合)、およびその他の特定のプロパティです。候補関数。[注:過負荷解決によって選択された機能は、コンテキストに適しているとは限りません。関数のアクセス可能性などの他の制限により、呼び出し元のコンテキストでの使用が不適切になる可能性があります。]

したがって、過負荷解決では、特定のコンテキストに適さない関数を選択できます。

于 2012-06-01T16:55:21.100 に答える
-1
switch(expression)

式は、整数型、または整数型への明確な変換が行われるクラス型である必要があります。

于 2012-06-01T16:54:33.090 に答える