2013-01-16 13 views
13

W poniższym kodzie spodziewam się błędu kompilatora, jeśli z powodu niejednoznaczności zdefiniowano więcej niż jednego operatora rzutowania.Pierwszeństwo przeładowanych operatorów obsady

#include <iostream> 
#include <sstream> 

struct A 
{ 
    operator const char*() { return "hello world\n"; } 
    operator float()  { return 123.0F; } 
    //operator int()   { return 49; } 
}; 

int main() 
{ 
    A a; 
    std::stringstream ss; 
    ss << a; 
    std::cout << ss.str(); 
    return 0; 
} 

Zamiast tego, jak długo tylko jeden operator numeryczny obsada jest definiowany następnie kompiluje bez błędów, bez ostrzeżenia, a obsada numeryczna jest używana w odniesieniu do operator const char *(). Kolejność deklarowanych operatorów nie ma znaczenia.

Jednak jeśli operator int() i operator float() są zarówno zdefiniowane potem dostać czego oczekiwałem od początku:

'operator <<' is ambiguous

Czy istnieją zasady pierwszeństwa dla odlewów, albo dlaczego kompilator wybrać obsadę numeryczną domyślnie? Rozumiem, że powinienem wyraźnie określić, co mam na myśli, ale moje pytanie jest na domyślny wybór, który kompilator robi.


Edycja: przy użyciu kompilatora MSVC 2010

+0

Nie będę polegał na tym, że istnieje pierwszeństwo. Wpisz, co masz na myśli. Po prostu użyj wyraźnej obsady. 'ss << static_cast (a);' – andre

+0

Złożyłem swój przykład, a g ++ daje mi "błąd: niejednoznaczne przeciążenie dla" operatora << "w" ss << a "". Tak więc przynajmniej g ++ działa zgodnie z oczekiwaniami. –

+1

Wygląda na to, że zależy to od kompilatora. Który kompilator używasz? – SztupY

Odpowiedz

4

Konwersje są klasyfikowane zgodnie z § 13.3.3.1 standardu C++. W szczególności, zdefiniowane przez użytkownika sekwencje konwersji odpowiednie dla twojego przykładu są uregulowane w § 13.3.3.1.2/1:

"Zdefiniowana przez użytkownika sekwencja konwersji składa się z początkowej standardowej sekwencji konwersji, po której następuje konwersja zdefiniowana przez użytkownika (12.3), a następnie druga standardowa sekwencja konwersji. [...] Jeżeli zdefiniowana przez użytkownika konwersja jest określona przez funkcję konwersji (12.3.2), początkowa standardowa sekwencja konwersji konwertuje typ źródła na niejawny parametr obiektu funkcja konwersji. "

wszystkie konwersje sekwencje tutaj obejmują:

  1. fikcyjne konwersję do rodzaju źródła utajonego parametru obiektu funkcji konwersji;
  2. zdefiniowana przez użytkownika konwersja;
  3. Konwersja tożsamości na typ wejściowy operator <<.

Wszystkie te sekwencje konwersji mają tę samą pozycję. Tak więc, połączenie powinno być niejednoznaczne. Jeśli tak nie jest, dla mnie jest to błąd kompilatora.

+1

Twoja odpowiedź jest myląca, ponieważ nie powinno tu być żadnych * "konwersji drugiego standardu" *, ponieważ zdefiniowana przez użytkownika konwersja przekształca się bezpośrednio w niezbędny typ. Więc tak, połączenie powinno być niejednoznaczne, ale nie z powodu, który podajesz w trzecim akapicie. –

+0

@ChristianRau: jeśli rozumiem poprawnie, co 13.3.3.1.2/1 mówi, konwersja zdefiniowana przez użytkownika jest * zawsze * konwersją trzyetapową, gdzie pierwszy krok może być fikcyjny: "początkowa standardowa sekwencja konwersji konwertuje źródło wpisz do niejawnego parametru obiektu funkcji konwersji. " –

+1

Tak, ale początkowe i drugie standardowe konwersje mogą być tylko operacjami typu "no-ops". W tym przypadku typy docelowe są już osiągane przez (środkową) konwersję zdefiniowaną przez użytkownika. Więc tak, wszystkie mają równą rangę, ale nie dlatego, że konwersje liczb całkowitych lub zmiennoprzecinkowych mają taką samą rangę (to nie ma znaczenia tutaj), ale ponieważ wszystkie one po prostu wymagają tej samej początkowej konwersji standardowej, a następnie zdefiniowanej przez użytkownika konwersja **, po której następuje ta sama konwersja drugiego standardu (no-op) **. –

Powiązane problemy