7

私が持っているとしましょう

#include <string>

class A
{
public:
    template<class T>
    operator T();

    A child();
};

void f()
{
    A a;
    std::string s1 = a;            // ok
    std::string s2 = a.child();    // error (line 34)

    s1 = a;           // error (line 36)
    s2 = a.child();   // error (line 37)

}

std::string コンストラクターは char* または std::string 参照のいずれかを取ることができるため、割り当てがあいまいになります。しかし、私のコンパイラ (VC++10) が 2 番目の代入について文句を言うのに、最初の代入については文句を言わないのはなぜですか?

オーバーロードされたコンストラクターではなく、テンプレート変換演算子を優先する方法を探しています。

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

1>------ Build started: Project: Plasma4Test, Configuration: Debug Win32 ------
1>  Plasma4Test.cpp
1>d:\bitbucket\vx\projects\plasma4test\plasma4test.cpp(34): error C2440: 'initializing' : cannot convert from 'A' to 'std::basic_string<_Elem,_Traits,_Ax>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          No constructor could take the source type, or constructor overload resolution was ambiguous
1>d:\bitbucket\vx\projects\plasma4test\plasma4test.cpp(36): error C2593: 'operator =' is ambiguous
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(772): could be 'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(_Elem)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(767): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const _Elem *)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(762): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const std::basic_string<_Elem,_Traits,_Ax> &)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          while trying to match the argument list '(std::string, A)'
1>d:\bitbucket\vx\projects\plasma4test\plasma4test.cpp(37): error C2593: 'operator =' is ambiguous
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(772): could be 'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(_Elem)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(767): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const _Elem *)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(762): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(const std::basic_string<_Elem,_Traits,_Ax> &)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          c:\program files\microsoft visual studio 10.0\vc\include\xstring(707): or       'std::basic_string<_Elem,_Traits,_Ax> &std::basic_string<_Elem,_Traits,_Ax>::operator =(std::basic_string<_Elem,_Traits,_Ax> &&)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>,
1>              _Ax=std::allocator<char>
1>          ]
1>          while trying to match the argument list '(std::string, A)'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
4

1 に答える 1

3

私には VC10 のバグのように思えますが、 とは関係ありませstd::string

バグの分離:

私はそれを次の例に落とし込みました:

#include <string>

class B
{
public:
    B(char const*) { }
    B(B&&) { }
};

class A
{
public:
    operator char* const () { return 0; }
    operator B () { return B(0); }
};

int main()
{
    A a;
    B b1 = a; // fine
    B b2 = A(); // error C2440: 'initializing' : cannot convert from 'A' to 'B'
                // No constructor could take the source type, or constructor
                // overload resolution was ambiguous.
}

クラスBには、ムーブ コンストラクターとコンストラクターがあり、const char*. b2から初期化しようとするとrvalue、VC10 は への変換演算子の選択に失敗するようBです。

Clang 3.2 と GCC 4.7.2 の両方で、変換演算子 to が選択されBます。

C++ 標準ルール:

C++ 標準命令のパラグラフ 8.5/16:

[このコピー初期化の場合] 「 13.3.1.4 で説明されているように、ソース型から宛先型、または (変換関数が使用されている場合は) その派生クラスに変換できるユーザー定義の変換シーケンスが列挙されます。最適なものは、オーバーロードの解決 (13.3) によって選択されます」

Aこの例でソース タイプ ( ) から宛先タイプ ( ) への使用可能なすべての変換シーケンスを考慮すると、のユーザー定義の変換関数をB含むへの変換には、さらに変換が必要です( )宛先タイプに到達するため。したがって、 (13.3.3.2 による)のユーザー定義変換関数を使用するものよりも 1 ステップ長いため、後者が推奨されます。Achar const*Bchar const* BAB

これは、VC10 のバグであることを確認しているようです。

于 2013-01-17T13:37:22.690 に答える