11

struct Value以下のコードが代わりに出力される理由がわかりませんint(これは、変換コンストラクターがではValueなくに変換していることを意味しintます)。(Visual C ++ 2012)

なぜこうなった?Value(int)コンパイラがコンストラクタを完全に無視するのはなぜですか?

#include <iostream>
#include <type_info>

using namespace std;

struct Value { Value(int) { } };

struct Convertible
{
    template<class T>
    operator T() const
    { throw typeid(T).name(); }
};

int main()
{
    try { Value w((Convertible())); }
    catch (char const *s) { cerr << s << endl; }
}

編集:

さらに奇妙なのはこれです(今回はC ++ 11のみ、GCC 4.7.2):

#include <iostream>
#include <typeinfo>

using namespace std;

struct Value
{
    Value(Value const &) = delete;
    Value(int) { }
};

struct Convertible
{
    template<class T>
    operator T() const
    { throw typeid(T).name(); }
};

int main()
{
    try { Value w((Convertible())); }
    catch (char const *s) { cerr << s << endl; }
}

これは次のようになります。

source.cpp: In function 'int main()':
source.cpp:21:32: error: call of overloaded 'Value(Convertible)' is ambiguous
source.cpp:21:32: note: candidates are:
source.cpp:9:3: note: Value::Value(int)
source.cpp:8:3: note: Value::Value(const Value&) <deleted>

コピーコンストラクターが削除された場合、なぜあいまいさがありますか?!

4

2 に答える 2

8

最初の例では、VisualStudioは正しくありません。呼び出しがあいまいです。C ++ 03モードのgccは、次のように出力します。

source.cpp:21:34: error: call of overloaded 'Value(Convertible)' is ambiguous
source.cpp:21:34: note: candidates are:
source.cpp:9:5: note: Value::Value(int)
source.cpp:6:8: note: Value::Value(const Value&)

コピーコンストラクターは暗黙的にデフォルト設定されていることを思い出してください。支配的な段落は13.3.1.3コンストラクターによる初期化[over.match.ctor]

クラスタイプのオブジェクトが直接初期化される場合[...]、オーバーロード解決によりコンストラクターが選択されます。直接初期化の場合、候補関数は、初期化されるオブジェクトのクラスのすべてのコンストラクターです。

2番目の例では、削除された関数は過負荷の解決に等しく関与します。これらは、削除された関数を選択するプログラムの形式が正しくない場合に、オーバーロードが解決された後にのみコンパイルに影響します。標準の動機付けの例は、浮動小数点型からのみ構築できるクラスです。

struct onlydouble {
  onlydouble(std::intmax_t) = delete;
  onlydouble(double);
};
于 2012-12-19T11:39:21.147 に答える
1

私はあなたのコードを試しました(Visual Studioバージョンのみ)。

組み込みのcopy-CTORがあるので、メインは次のようになります。

int main()
{
    try { Value w((struct Value)(Convertible())); }
    catch (char const *s) { cerr << s << endl; }
}

コンパイラーは、Value(int)ではなくコピーCTORを使用することを選択しました。

次のように変更します。

int main()
{
    try { Value w((int)(Convertible())); }
    catch (char const *s) { cerr << s << endl; }
}

「int」を印刷しました。

于 2012-12-19T11:25:44.293 に答える