Próbuję zaktualizować stary projekt, który został zbudowany w studio graficznym 2005 do wykorzystania w studio wizualnym 2012, a ja Otrzymuję błąd, którego nie mogę rozwiązać.Kod operatora obslugi typu C++, który nie będzie kompilowany w Visual Studio 2012, ale działał dobrze w Visual Studio 2005
Kod, który działa dobrze pod 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;
}
Kiedy jestem kompilacji to pod VS2012 pojawia się błąd w wierszu "wstring str = v;", błąd jest:
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
Mogę to naprawić, zmieniając sygnaturę operatora z "operator wstring() const" na "operator const wstring &() const". Ale dlaczego oryginalny kod nie działa, mimo że działa w VS2005.
Nie otrzymuję błędu na linii "int i = int_val;".
To również kompiluje i działa dobrze z GCC (g ++) w cygwin (wersja 4.5.3).
Aktualizacja Aby naprawdę zasymulować mój prawdziwy problem, niektóre informacje zostały pominięte w powyższym przykładowym kodzie. Pomiędzy klasą Value a użyciem jest kilka innych klas. Jeden, który wygląda tak:
class Config
{
public:
virtual Value getValue(const string& key) const = 0;
Value operator()(const string& key)
{
return getValue(key);
}
};
A Wykorzystanie const wstring VALUE2 = config ("klucz");
To da błąd powyżej podczas kompilacji, ale również IntelliSense da inne wskazówki, co jest nie tak i mówi: "Zastosowanie ma więcej niż jedna konwersja zdefiniowana przez użytkownika z" Wartość "do" const std :: wstring ":" i wskazuje zarówno na zwykły konstruktor, jak i na konstruktor ruchu podstawowego. Wydaje się, że ma to coś wspólnego z rvalues i czytałem o tym i rozumiem podstawy. Ale prawdopodobnie wiele brakuje mi.
uważam, że mogę rozwiązać ten problem poprzez zmianę wykorzystania do: const wstring & & value = config ("key");
Następnie wydaje się, że kompilator VS2012 rozumie, który konstruktor powinien wtedy użyć.
Pytania: * Czy istnieje sposób, aby nie używać w tym przykładzie & &? * Co tak naprawdę się dzieje?
kładę się przykładowy kod na GitHub: https://github.com/Discordia/ImplicitTypeConversion
Kompiluje się dobrze z Clang Trunk, więc domyślam się, że jest to błąd z ich zbyt wysoką rozdzielczością, która nie wybiera szablonu przed szablonem (w różnych możliwych LUW). Zauważ, że istnieją dwa opłacalne konstruktory: jeden pobierający 'wstring &&', a także ten, który przyjmuje 'wchar_t const *'. Ten pierwszy wywołałby operację konwersji "wstring", podczas gdy druga wywoła szablon konwersji. – Xeo
@Xeo: Lub typowy błąd w wielu kompilatorach. W szybkim pobieżnym wyglądzie w standardzie * wydaje się, że VS może być właśnie tutaj. Nie znalazłem żadnej reguły, która określałaby, że wersja bez szablonu ma pierwszeństwo przed szablonową, a bez tego pierwszeństwa operator konwersji jest niejednoznaczny podczas konwersji na 'std :: wstring', a standard wymaga, aby kod się nie powiódł. –
@David: '§13.3.3/1:' "Biorąc pod uwagę te definicje, realna funkcja" F1 "jest zdefiniowana jako lepsza funkcja niż inna możliwa funkcja ' F2' jeśli [...] "F1" jest funkcja non-template i 'F2' to specjalizacja szablonów funkcji [...]" – Xeo