2013-08-30 16 views
5

Mam klasę, którą napisałem, która nie usuwa typu. Interfejs publiczny to:Dlaczego ta obsada jest niejednoznaczna?

template <typename T> 
value(const T &t); 

value(value &&v); 

template <typename T> 
operator T() const; 

Kiedy tworzę instancję wartości ze std :: string, nie mam żadnych problemów, wszystko działa zgodnie z oczekiwaniami. Kiedy próbuję uzyskać std :: string z powrotem, używając static_cast<std::string>(val), gdzie val jest instancją wartości, która trzyma std :: string, pojawia się następujący komunikat o błędzie z VS2012:

błędu C2440: ' static_cast „: nie można przekonwertować z«value»do std :: string”

nie konstruktora może trwać rodzaj źródła, lub rozdzielczość przeciążenie konstruktor był niejednoznaczny

Gdybym wykomentuj operatora cast szablonie i dodać operator std::string() const następnie kompiluje. Sądzę, że coś pomiędzy konstruktorami std :: string a operatorem rzutowania szablonowego ma taką samą dobroć dopasowania. Czy ktoś mógłby zasugerować, co się dzieje i jak to naprawić?

+0

Czy komunikat o błędzie pokazuje kandydatów? –

+3

Podaj przykład kompilacji (w miarę możliwości aż do wskazanego błędu). –

+1

Oto minimalny przykład, który napisałem: http://codepad.org/XJ2Jv5fT – Dave

Odpowiedz

6

Igor wyjaśnił problem. Oto moje sugerowane rozwiązanie:

Twoja klasa jest przeznaczona wyłącznie do przechowywania jednego typu obiektów naraz, więc wyraź to wyraźnie. Wymień funkcje konwersji z prawdziwą funkcją:

template <typename T> 
T get() const; 

Teraz nazywają to tak:

std::string myString = myValue.get<std::string>(); 

Nie dwuznaczności. Nie ma szans na wywołanie niewłaściwej funkcji i zepsucie wszystkiego. I twierdzę, że jest teraz bardziej czytelny.

6

std::string ma kilka konstruktorów, które można wywołać z jednym parametrem - np. jeden pobierający const string&, a drugi pobierający const char*. Do czego zatem należy się ustosunkować pod T?

od C++ standardzie:

5.2.9p4 W przeciwnym przypadku ekspresji E można bezpośrednio przekształcić w rodzaju T stosując static_cast formy static_cast<T>(e) jeżeli zgłoszenie T t(e); jest sensowne dla niektórych wynalazł zmienna tymczasowa t.

W twoim przypadku deklaracja std::string t(val); jest źle sformułowana.

+0

'std :: string', jak zapewnia obsada. Z czego jest zbudowany, zależy od kodu w funkcji. –

+0

Widzę, co masz na myśli przez tę odpowiedź, ale wydaje mi się logiczne, że wybiera ona bezpośrednią (jednoetapową) konwersję na 'std :: string' zamiast jakiejkolwiek pośredniej (dwustopniowej) konwersji na parametr, który można przekazać do konstruktora dla 'std :: string' – Dave

+0

@Neil Kirk:" 5.2.9p4 W przeciwnym razie wyrażenie 'e' można jawnie przekonwertować na typ' T' używając 'static_cast' w formularzu 'static_cast (e)' jeśli deklaracja 'T t (e);' jest dobrze sformułowana, dla pewnej wymyślonej zmiennej tymczasowej 't'". W tym przypadku deklaracja 'string t (val);' nie jest dobrze sformułowana. –

5

Następujące prace z std :: string (jeśli możesz zwrócić referencję).

static_cast<const std::string&>(val); 
+0

potwierdzone http://codepad.org/w7VKXUcs. To jest interesujące. Nie pomyślałabym, żeby rzucić referencję. Niezbyt czytelne, więc uniknęłbym go w prawdziwym kodzie, chyba że jest to absolutnie konieczne. – Dave

+0

Bardzo interesujące i nowatorskie rozwiązanie! –

Powiązane problemy