Rozważ ten kod:
#include <vector>
#include <iostream>
enum class A
{
X, Y
};
struct Test
{
Test(const std::vector<double>&, const std::vector<int>& = {}, A = A::X)
{ std::cout << "vector overload" << std::endl; }
Test(const std::vector<double>&, int, A = A::X)
{ std::cout << "int overload" << std::endl; }
};
int main()
{
std::vector<double> v;
Test t1(v);
Test t2(v, {}, A::X);
}
To drukuje:
vector overload
int overload
Dlaczego nie powoduje to błędu kompilacji z powodu niejednoznacznej rozdzielczości przeciążenia? Jeśli drugi konstruktor zostanie usunięty, otrzymamy vector overload
dwa razy. Jak / według jakiej miary jest int
jednoznacznie lepsze dopasowanie {}
niżstd::vector<int>
?
Podpis konstruktora można z pewnością jeszcze bardziej przyciąć, ale właśnie zostałem oszukany przez równoważny fragment kodu i chcę się upewnić, że nic ważnego nie zostanie utracone w tym pytaniu.
c++
language-lawyer
overload-resolution
Max Langhof
źródło
źródło
{}
jako blok kodu, przypisuję 0 do zmiennych - przykład: const char x = {}; jest ustawiony na 0 (null char), to samo dla int itp.{}
skutecznie działa w niektórych szczególnych przypadkach, ale ogólnie nie jest poprawne (na początek,std::vector<int> x = {};
działa,std::vector <int> x = 0;
nie działa). To nie jest tak proste jak „{}
przypisuje zero”.struct A { int x = 5; }; A a = {};
nie przypisuje zera w żadnym sensie, konstruujeA
za.x = 5
. Inaczej jest w przypadkuA a = { 0 };
inicjalizacjia.x
na zero. Zero nie jest nieodłączne{}
, jest nieodłączne od tego, jak każdy typ jest konstruowany domyślnie lub inicjowany na wartości. Zobacz tutaj , tutaj i tutaj .Odpowiedzi:
Jest na [over.ics.list] , moje wyróżnienie
std::vector
Jest inicjowany przez konstruktora i kulą w śmiałych uzna to za określony użytkownik converison. Tymczasem, na przykładint
, jest to konwersja tożsamości, więc przewyższa pozycję pierwszego c'tora.źródło
0
ma typ,int
ale nie piszestd::vector<int>
, jak to się dzieje, że „jakby” wpisuje się w „nietypowy” charakter{}
?std::vector<int>
. Jak powiedziałeś, spodziewałem się, że „typ parametru ostatecznie decyduje, jaki jest typ argumentu”, a{}
„typ” (że tak powiem)std::vector<int>
nie powinien wymagać konwersji (braku tożsamości), aby zainicjowaćstd::vector<int>
. Standard oczywiście mówi, że tak, więc o to chodzi, ale nie ma to dla mnie sensu. (Pamiętaj, że nie twierdzę, że ty lub standard jesteście w błędzie, po prostu próbuję pogodzić to z moimi modelami mentalnymi.)