8

Ostatnio napisałem bardzo prostą klasę.std :: initializer_list dedukcja typu

class C 
{ 
public: 
    void AddString(std::initializer_list<std::pair<const char*,int>> x) 
    { 
      //irrelevant 
    } 
}; 

int main() 
{ 
      C c; 
      c.AddString({ {"1",1}, {"2", 2}, {"3", 3} }); 
      .... //other unimportant stuff 
      return 0; 
} 

Ku mojej miłej niespodziance skompilował i działał poprawnie. Czy ktoś może mi wyjaśnić, w jaki sposób kompilator był w stanie wydedukować zagnieżdżone, zblokowane inicjatory, dla std::pair? Używam MSVS 2013

Odpowiedz

9
c.AddString({ {"1",1}, {"2", 2}, {"3", 3} }); 

Jesteś przechodzącą usztywnione-init-listy, która sama w sobie zawiera zagnieżdżonych Brace-Init-List s do AddString. Argument może być zgodny z parametrem std::initializer_list<std::pair<const char*,int>>, jeśli wewnętrzna lista inicjująca ze wzmocnioną stacją może zostać przekształcona w s na std::pair<const char*,int>.

Ten proces rozwiązywania przeciążenia występuje w dwóch etapach; najpierw podejmowana jest próba dopasowania konstruktorów std::pair, które przyjmują argument std::initializer_list. Ponieważ std::pair nie ma takiego konstruktora, występuje drugi etap, w którym inni konstruktorzy std::pair<const char*,int> są wymieniani jako char const[2] i int jako argumenty. Spowoduje to dopasowanie następującego konstruktora pair, ponieważ char const[2] jest niejawnie przekształcalny na char const *, a sam konstruktor nie jest explicit.

template< class U1, class U2 > 
constexpr pair(U1&& x, U2&& y); 

Cytowanie N3337 §13.3.1.7/1 [over.match.list]

gdy przedmioty nie zagregowanym klasy typu T to lista inicjalizacji (8.5.4), rozdzielczość przeciążania wybiera konstruktor w dwóch fazach:
— Początkowo kandydatami są konstruktory listy inicjalizacyjnej (8.5.4) klasy T, a lista argumentów składa się z inicjalizatora er lista jako pojedynczy argument.
przypadku braku realnej initializer-lista konstruktor zostanie znaleziony, rozdzielczość przeciążenie jest wykonywana ponownie, gdzie funkcje kandydujące są wszystkie konstruktory klasy T i lista jej argumentów składa się z elementów listy inicjatora.

Jeśli na liście inicjalizacyjnej nie ma elementów, a T ma domyślny konstruktor, pierwsza faza jest pomijana. W inicjalizacji listy-kopiowania, jeśli wybrany jest konstruktor explicit, inicjalizacja jest źle sformułowana.

+0

Świetna odpowiedź, znacznie bardziej kompletna! – vsoftco

+0

Dziękuję, to wyjaśnia pewne rzeczy ... Muszę zrozumieć nieco więcej o rozładowaniu obciążenia, gdy zaangażowane są wzmocnione listy inicjujące. – pebbleonthebeach

+0

@pebbleonthebeach Zasady usuwania przeciążenia podczas inicjalizacji listy są tymi, które skopiowałem - wkleiłem powyżej. Jeśli chodzi ci o ogólne zaznajomienie się z problemem przeciążenia, sugeruję, aby zacząć od [tego wideo] (https://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-Cpp-3-of-n) (obejrzyj całą serię, jeśli znajdziesz czas). – Praetorian

Powiązane problemy