Разница между возвращаемым значением и локальной переменной

Предположим, у меня есть

#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) жалуется на второе назначение, а не первое?

Я ищу способ отдать приоритет оператору преобразования шаблона, а не перегруженному конструктору.

Я получаю следующие ошибки:

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 ==========

1 ответ

Похоже, ошибка 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 из rvalueVC10, похоже, не может выбрать оператора преобразования в B,

И Clang 3.2, и GCC 4.7.2 выбирают оператор преобразования в B,

СТАНДАРТНЫЕ ПРАВИЛА C++:

Пункт 8.5/16 Стандартных мандатов C++:

[для этого случая инициализации копирования] перечисляются определяемые пользователем последовательности преобразования, которые могут преобразовывать из типа источника в тип назначения или (когда используется функция преобразования) в его производный класс, как описано в 13.3.1.4, и лучший выбирается через разрешение перегрузки (13.3)"

Если мы рассмотрим все доступные последовательности преобразования в нашем примере из типа источника (A) к типу назначения (B), то тот, который включает в себя Aпользовательская функция преобразования в char const* требует дальнейшего преобразования (сделано через Bконструктор, который принимает char const*) для достижения типа назначения B, Таким образом, это на один шаг дольше, чем тот, который использует Aпользовательская функция преобразования в B (согласно 13.3.3.2), что делает последний предпочтительным.

Это, кажется, подтверждает, что это ошибка VC10.

Другие вопросы по тегам