Подтвердить что ты не робот

Код сценария типа С++, который не будет компилироваться в visual studio 2012, но отлично работал в visual studio 2005

Я пытаюсь обновить старый проект, созданный с помощью visual studio 2005, для использования visual studio 2012, и я получаю сообщение об ошибке, которое я не могу решить.

Код, который отлично работает в VS2005:

#include <iostream>
#include <string>
#include <sstream>

using std::cout;
using std::wcout;
using std::endl;
using std::wstring;
using std::string;


class Value 
{
public:
    Value(const wstring& value) 
    {
        v = value;
    }

    Value(Value& other)
    {
        this->v = other.v; 
    }

    template<typename T>
    operator T() const
    {
        T reply;
        std::wistringstream is;
        is.str(v);
        is >> reply;
        return reply;
    } 

    operator wstring() const 
    {
        return v;
    }


private:
    wstring v;
};


int main()
{
    Value v(L"Hello World");

    wstring str = v;
    wcout << str << endl;

    Value int_val(L"1");
    int i = int_val;

    cout << i + 1 << endl;

    return 0;
}

Когда я компилирую это под VS2012, я получаю сообщение об ошибке в строке "wstring str = v;", ошибка:

error C2440: 'initializing' : cannot convert from 'Value' to 'std::basic_string<_Elem,_Traits,_Alloc>'
1>          with
1>          [
1>              _Elem=wchar_t,
1>              _Traits=std::char_traits<wchar_t>,
1>              _Alloc=std::allocator<wchar_t>
1>          ]
1>          No constructor could take the source type, or constructor overload resolution was ambiguous

Я могу его исправить, изменив сигнатуру оператора от оператора wstring() const 'до' operator const wstring &() const '. Но почему исходный код не работает, хотя он работает в VS2005.

Я не получаю ошибку в строке "int я = int_val;".

Это также компилируется и работает отлично с GCC (g++) в cygwin (версия 4.5.3).

Обновление Чтобы действительно смоделировать мою реальную проблему, в приведенном выше примере была некоторая информация. Между классом Value и использованием используется несколько других классов. Один из них выглядит следующим образом:

class Config
{
public:
    virtual Value getValue(const string& key) const = 0;

    Value operator()(const string& key) 
    {
         return getValue(key);
    }
};

И использование   const wstring value2 = config ( "ключ" );

Это даст ошибку выше при компиляции, но также IntelliSense даст другие намеки на то, что не так, и говорит: "Применяется более одного пользовательского преобразования от" Value "до" const std:: wstring ":" и это указывает как на обычный конструктор, так и на конструктор перемещения basic_string. Похоже, что это имеет какое-то отношение к rvalues, и я читал об этом и понимаю основы. Но, вероятно, много чего мне не хватает.

Я нахожу, что могу исправить эту проблему, изменив использование:       const wstring && value = config ( "ключ" );

Тогда похоже, что компилятор VS2012 понимает, какой конструктор он должен использовать тогда.

Вопросы:  * Есть ли способ не использовать && в этом примере?  * Что на самом деле происходит здесь?

Я приведу пример кода на GitHub: https://github.com/Discordia/ImplicitTypeConversion

4b9b3361

Ответ 1

В простых (надеюсь, не упрощенных) условиях, с С++ 11, вам нужно будет начать думать о ссылках в терминах lvalue и rvalue. В основном, С++ 11 дает вам возможность обрабатывать операции над ссылками по-разному в зависимости от того, имеете ли вы дело с "временным" объектом. Это дает вам возможность делать такие вещи, как перенос данных внутри вашего объекта, а не копирование в разных ситуациях. Нижняя сторона этого - эффект, который вы видите, где старый код недостаточно специфичен, о котором вы имеете дело. Более того, это не совсем то, что можно полностью объяснить в коротком ответе SO, но предыдущие ответы дали несколько хорошие места. Я бы переработал ваш код, чтобы предоставить как rvalue, так и lvalue-операторы (что похоже на то, что вы уже на своем пути).