c ++ 11 — код оператора приведения типа C ++, который не будет компилироваться в 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

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

Я не получаю сообщение об ошибке «int i = 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&& значение = config («ключ»);

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

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

Я разместил пример кода на GitHub:
https://github.com/Discordia/ImplicitTypeConversion

11

Решение

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

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]