Sto cercando di aggiornare un vecchio progetto che è stato creato con Visual Studio 2005 per utilizzare Visual Studio 2012 e I sto ottenendo un errore che non posso risolvere.Codice di operatore cast di tipo C++ che non verrà compilato in Visual Studio 2012, ma ha funzionato bene in Visual Studio 2005
Il codice che funziona bene sotto 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;
}
Quando Sto compilando questo sotto VS2012 ottengo un errore sulla linea "wstring str = v;", l'errore è:
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
Posso risolvere il problema cambiando la firma dell'operatore da 'operator wstring() const' a 'operator const wstring &() const'. Ma perché il codice originale non funziona, anche se funziona in VS2005.
Non ricevo un errore sulla riga "int i = int_val;".
Questo compila anche e gira bene con GCC (g ++) in cygwin (versione 4.5.3).
Aggiornamento Per simulare realmente il mio problema reale, alcune informazioni non erano disponibili nel codice di esempio riportato sopra. Tra la classe Value e l'uso ci sono poche altre classi. Uno che simile a questa:
class Config
{
public:
virtual Value getValue(const string& key) const = 0;
Value operator()(const string& key)
{
return getValue(key);
}
};
E l'utilizzo const wstring valore2 = config ("chiave");
Questo darà l'errore sopra durante la compilazione ma anche IntelliSense fornirà altri suggerimenti su cosa è sbagliato e dice: "Più di una conversione definita dall'utente da" Valore "a" const std: wstring "vale:" e punta sia al costruttore regolare che al costruttore di mosse di basic_string. Quindi sembra che abbia qualcosa a che fare con i rvalues da fare e ho letto su questo e capisco le basi. Ma ci sono probabilmente molte cose che mi mancano.
trovo che posso risolvere questo problema modificando l'utilizzo di: const wstring & & value = config ("chiave");
Quindi sembra che il compilatore VS2012 capisca quale costruttore dovrebbe utilizzare.
Domande: * C'è un modo per non utilizzare & & in questo esempio? * Che cosa sta veramente succedendo qui?
ho messo il codice di esempio su GitHub: https://github.com/Discordia/ImplicitTypeConversion
Compilano bene con Clang Trunk, quindi suppongo che sia un bug con la loro risoluzione di sovraccarico che non preleva il non-modello prima del modello (attraverso diversi possibili UCS). Si noti che esistono due costruttori validi: quello che prende 'wstring &&', e anche quello che prende' wchar_t const * '. Il primo invoca il comando di conversione 'wstring', mentre il secondo invoca il modello di conversione op. – Xeo
@Xeo: o un errore comune in più compilatori. Su un rapido sguardo superficiale nello standard sembra * che VS potrebbe essere proprio qui. Non ho trovato alcuna regola che determini che la versione non-template abbia la precedenza su quella basata su modelli, e senza tale precedenza l'operatore di conversione è ambiguo quando converte in 'std :: wstring' e lo standard richiede che il codice fallisca. –
@David: '§13.3.3/1:' "Date queste definizioni, una funzione valida' F1' è definita come una funzione migliore di un'altra funzione valida 'F2' se [...]' F1' è un la funzione non-template e 'F2' è una specializzazione del modello di funzione [...]" – Xeo