7

(gcc 4.3.4 で) コンパイルしようとすると、このコード スニペット:

enum SimpleEnum {
    ONEVALUE
};

void myFunc(int a) {
}

void myFunc(char ch) {
}

struct MyClass {
    operator int() const { return 0; };
    operator SimpleEnum() const { return ONEVALUE; };
};

int main(int argc, char* argv[]) {
    myFunc(MyClass());
}

次のエラーが表示されます。

test.cc: In function "int main(int, char**)":
test.cc:17: error: call of overloaded "myFunc(MyClass)" is ambiguous
test.cc:5: note: candidates are: void myFunc(int)
test.cc:8: note:                 void myFunc(char)

問題が何であるかを(ほとんど)理解していると思います。つまり、(かなり単純化して)「char」と「enum」について話しても、それらはすべて整数であり、オーバーロードがあいまいです。

とにかく、私が本当に理解していないのは、myFuncの 2 番目のオーバーロード またはMyClassの変換演算子の 1 つを削除すると、コンパイル エラーが発生しないことです。

この問題のために古いコードを大量に変更する予定なので (古いバージョンの HP-UX aCC から Linux の g++ 4.3.4 にコードを移植しています)、全体をよりよく理解したいと思います。コードを変更する最善の方法を選択するために。

よろしくお願いします。

4

3 に答える 3

4

enums は、Cとは異なり、C++ の型です。

enum->charenum->の両方に暗黙の変換がありますint。コンパイラは、どれを選択すればよいかわかりません。


編集:さまざまなテストを試した後:

  • カスタム変換MyClass->の定義intが削除されると、コードがコンパイルされます。

  • ここでは、enum から への暗黙的な変換が行われintているため、これはコンパイラによって への変換よりも優先されcharます。ここでテストします

  • の定義void myFunc(int)が削除されると、コンパイルが失敗します。

  • コンパイラーは から への変換を試行しMyClasscharユーザー定義の変換 operator がなく、ユーザー定義と使用可能性char()の両方があることを検出しました。ここでテストしますint()SimpleEnum()

  • char()コンパイルに変換演算子を追加するMyClassと、そうでない場合と同じエラーで失敗します。

  • ここでテストします

したがって、ここで私が思いついた結論は、最初に投稿されたコードで、コンパイラは の 2 つのオーバーロードされたバージョンのどちらを呼び出すかを決定するmyFunc必要があるということです。両方の変換が可能であるため:

  1. MyClassintユーザー定義の変換演算子を介して。
  2. MyClassintユーザー定義の変換 ( MyClassto SimpleEnum) + 暗黙の変換 ( SimpleEnumto char)を介して to

コンパイラは、どちらを使用するかを認識していません。

于 2011-09-15T16:16:23.727 に答える
4

からの変換MyClassはあいまいです。 への変換intと列挙型への変換が 1 つずつあり、それ自体が暗黙的に に変換可能intであり、どちらも同等に適切な変換です。ただし、必要な変換を指定することで、呼び出しを明示的にすることができます。

myfunc(int(MyClass()));

intあるいは、なぜとの別々のオーバーロードを持つ関数を持っているのかを再考したいかもしれませんchar。おそらくそれも再設計できるでしょう。

于 2011-09-15T16:22:45.523 に答える
1

int オーバーロードが呼び出されることを期待していました。いくつかのコンパイラを試してみましたが、異なる結果が得られました。何かを削除する場合はint、列挙型には int への標準変換があるため、ユーザー変換演算子を に削除します。

于 2011-09-15T16:23:31.137 に答える