8

Recentemente ho scritto una classe molto semplice.std :: initializer_list tipo deduzione

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; 
} 

Con mia piacevole sorpresa ha compilato e lavorato correttamente. Qualcuno può spiegarmi come il compilatore è stato in grado di dedurre gli inizializzatori rinforzati nidificati erano per un std::pair? Sto usando MSVS 2013.

risposta

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

si sta passando un rinforzato-init-list, che a sua volta contiene nested brace-init-list s per AddString. L'argomento può corrispondere al parametro std::initializer_list<std::pair<const char*,int>> se l'interno -init-list rinforzato s può essere convertito in std::pair<const char*,int>.

Questo processo di risoluzione del sovraccarico avviene in due passaggi; prima viene effettuato un tentativo di abbinamento ai costruttori di std::pair che accettano un argomento std::initializer_list. Poiché std::pair non dispone di tale costruttore, si verifica il secondo passaggio, in cui gli altri costruttori di std::pair<const char*,int> sono enumerati con char const[2] e int come argomenti. Ciò corrisponderà al seguente costruttore pair perché char const[2] è implicitamente convertibile in char const * e il costruttore stesso non è explicit.

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

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

Quando gli oggetti di tipo non-aggregato classe T sono elenco inizializzata (8.5.4), la risoluzione di sovraccarico seleziona il costruttore in due fasi:
— Inizialmente, le funzioni candidate sono i costruttori di inizializzatore-elenco (8.5.4) della classe T e l'elenco di argomenti consiste dell'inizializzazione elenco come un singolo argomento.
Se non viene trovato alcun costruttore di inizializzatore-elenco valido, viene eseguita nuovamente la risoluzione di sovraccarico, dove le funzioni candidate sono tutti i costruttori della classe T e l'elenco degli argomenti è costituito dagli elementi dell'elenco di inizializzazione.

Se l'elenco di inizializzazione non ha elementi e T ha un costruttore predefinito, la prima fase viene omessa. Nell'inizializzazione dell'elenco di copia, se viene scelto un costruttore , l'inizializzazione non è corretta.

+0

Ottima risposta, molto più completa! – vsoftco

+0

Grazie, che chiarisce alcune cose .. Devo capire un po 'di più sulla risoluzione del carico quando sono coinvolti gli elenchi di init rinforzati. – pebbleonthebeach

+0

@pebbleonthebeach Le regole per la risoluzione del sovraccarico quando è in corso l'inizializzazione dell'elenco sono quelle che ho copiato sopra. Se intendi che devi familiarizzare con la risoluzione del sovraccarico in generale, ti suggerisco di iniziare con [questo video] (https://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-Cpp-3-of-n) (guarda l'intera serie se riesci a trovare l'ora). – Praetorian