2015-06-25 15 views
10

Il seguente codice sembra funzionare correttamente su Clang ++ e GCC:std :: vector in avanti tipo dichiarato

#include <vector> 

class A { 
private: 
    int i; 
    std::vector<A> children; 
public: 
    A& add(); 
}; 

A& A::add() { children.emplace_back(); return children.back(); } 

int main() { 
    A a; 
    A& a2 = a.add(); 
} 

Quando il membro di dati std::vector<A> è dichiarato, A è ancora un tipo incompleto. Lo stesso quando si utilizza std::vector<B> e B è stato inoltrato solo con class B;. Dovrebbe funzionare con std::vector poiché contiene solo un puntatore a A.

È garantito il funzionamento o il comportamento non definito?

risposta

14

Questo comportamento non è definito in C++ 14 e precedenti; ben definito in C++ 17 (se è 17).

[res.on.functions]/P2, punto 2.7:

In particolare, gli effetti sono indefiniti nei seguenti casi:

  • [...]
  • se un tipo incompleto (3.9) viene utilizzato come argomento modello durante l'istanziazione di un componente del modello, a meno che non sia specificamente consentito per tale componente il componente .

In C++ 14 e precedenti, std::vector non "specificamente permettere" questo. Quindi il comportamento non è definito.

per C++ 17, N4510, adottata nel corso della riunione maggio 2015 della commissione, rilassa questa regola per vector, list e forward_list.

1

In base alla sezione "Parametri modello" da cppreference.com questo potrebbe funzionare (a seconda dell'utilizzo effettivo del contenitore) in C++ 17 standard, ma non in C++ 14 e precedenti. Probabilmente stai usando versioni dei compilatori che implementano questa parte dello standard C++ 17.

+0

In realtà, la carta accettata per C++ 17 è stata accettata con solo 'std :: list',' std :: forward_list' e 'std :: vector' in modo che GCC, Clang e MSVC siano conformi fuori dalla scatola . – Morwenn