2017-12-28 156 views
8

Istnieje funkcja globalna (tylko przykład):Usuwanie przeciążonej funkcji. C++ 11. Call of przeciążony ... jest niejednoznaczny

void func(int i) 
{ 
    std::cout << i + 100 << std::endl; 
} 

Zakładam, że wywołanie tej funkcji z argumentem char nie ma sensu, więc używam usunięcia:

void func(char) = delete; 

więc oczekiwać, że następujące połączenia powinno być możliwe:

func(1); 
func(3.1); 
func(true); 

I zadzwonić z argumentu char powinny być zabronione:

func('a'); 

Ale to nie jest prawda. Dzwoniąc func('a') uzyskać zgodnie z oczekiwaniami:

error: use of deleted function ‘void func(char)’ 

Ale podczas wywoływania func(2.3) uzyskać:

error: call of overloaded ‘func(double)’ is ambiguous 

Dlaczego mam ten błąd? Nie usuwając funkcji z argumentami char, zmieniono na int i wywołano func (int), dlaczego teraz jest zabronione?

+0

_ "Dlaczego pojawia się ten błąd?" _ Czy wiesz, że 'char' może automatycznie zostać przekonwertowany na' int' i 'double'? – user0042

+5

Wszystko, co masz po ** EDYCJI **, wydaje się być odpowiedzią na twoje pytanie. Jeśli to twoja odpowiedź, usuń ją z pytania i * opublikuj jako odpowiedź *. Jeśli, jak się wydaje, po prostu powtarzasz istniejący, nie publikuj duplikowanej odpowiedzi; po prostu usuń go ze swojego pytania. –

Odpowiedz

12

Po wywołaniu

func(2.3) 

miniesz double do funkcji. Listę kandydatów zawiera zarównofunc(int) i func(char), jak rozdzielczość przeciążenie dzieje beforedelete kicks in:

Jeśli funkcja jest przeciążony, rozdzielczość przeciążenie odbywa się pierwszy, a program jest tylko źle sformułowane, czy usunięte funkcją było Wybrano Ref: cppreference.com, patrz Avishai's answer, aby uzyskać precyzyjne standardowe oferty.

teraz double można przekształcić zarówno char i int, stąd niejednoznaczności.

Bez usuwania funkcji z argumentami znaków double został przekonwertowany na int i wywołano func (int), dlaczego teraz jest zabronione?

Otrzymasz błąd niejednoznaczności nawet bez delete ing wersję char, zobaczyć na żywo here. Oczywiście, jeśli zdefiniujesz tylko func(int), wtedy nie będzie żadnych niejednoznaczności, więc double z przyjemnością zostanie przekonwertowany na int.

+0

Nie dostaję błędu niejednoznaczności w przykładzie [this] (http://coliru.stacked-crooked.com/a/920af47ca988ed2e). –

+1

@AdamStepniak Zobacz edycję. W twoim linku masz tylko jedną deklarację, 'func (int)', więc nie ma dwuznaczności konwersji. Jeśli dodasz 'func (char)', bez względu na 'delete'd lub nie, dostaniesz niejasności, jak wspomniano w odpowiedzi. Należy pamiętać, że 'delete' został rozwiązany ** po ** rozdzielczości przeciążenia, zobacz http://en.cppreference.com/w/cpp/language/function#Deleted_functions, więc niejednoznaczności zdarzają się tak, jakbyś pisał przed Kod C++ 11. – vsoftco

0

Jest nadal niejednoznaczny, ponieważ kompilator próbuje rozwiązać problem przed sprawdzeniem usuniętych funkcji. Zobacz:

§8.4.3 Usunięte definicje

Program odwołujący się do usuniętej funkcji pośrednio lub jawnie, inny niż jej zadeklarowanie, jest źle sformułowany. [ Uwaga: Obejmuje to wywołanie funkcji niejawnie lub jawnie i utworzenie dla tej funkcji wskaźnika lub wskaźnika do członka . Dotyczy to nawet odniesień w wyrażeniach, które nie są potencjalnie oceniane. Jeżeli funkcja jest przeciążona, odwołuje się do niej tylko wtedy, gdy wybrana funkcja jest wybrana z powodu przeciążenia. - koniec uwaga ]

§13.3.3.1 niejawne sekwencje przetwarzania:

niejawne sekwencje konwersji są tylko związane z typem, CV, kwalifikacje i kategorii wartości argumentu i jak te są konwertowane, aby dopasować odpowiednie właściwości parametru. Inne właściwości, takie jak czas życia, klasa pamięci, wyrównanie, dostępność argumentu, to, czy argument jest polem bitowym i czy funkcja jest usuwana (8.4.3), są ignorowane. Tak więc, chociaż można zdefiniować niejawną sekwencję konwersji dla danej pary argumentów i parametrów, konwersja z argumentu do parametru może nadal być źle sformułowana w ostatecznej analizie.

+0

Kompilator _didn't_ wybierz 'func (char)', a fakt, że funkcja została usunięta jest w 100% nieistotny dla problemu. –

1

Za każdym razem, gdy do parametru funkcji przekazywane jest dopasowanie nieścisłe, należy wykonać konwersję. Gdy masz dwie funkcje, niezależnie od tego, czy są one usuwane, nadal uczestniczą w przeciążeniu. Kompilator wybiera najlepsze dopasowanie, a następnie generuje wywołanie do niego lub kończy się niepowodzeniem, jeśli funkcja jest niedostępna lub usunięta.

Aby zadziałała rezerwa przeciążenia, tworzy zestaw funkcji kandydujących, a następnie widzi, która z nich ma najkrótszą ścieżkę konwersji do zestawu parametrów. Jeśli chodzi o reguły, wszystkie wbudowane typy liczbowe są konwersją "równą". Dlatego jeśli zadzwonisz z 2.5, który jest podwójnym, to musi konwertować i może konwertować równo na char LUB na int, z tym samym rankingiem, więc wywołanie jest niejednoznaczne.

+0

Uwaga: istnieje kilka przypadków, w których usunięte funkcje nie biorą udziału w rozwiązywaniu przeciążenia (zwykle wymaga to specjalnych funkcji klasy klasy); ale przypadek OP nie jest jednym z tych –

+0

@ M.M dzięki za to wyjaśnienie. –

Powiązane problemy