2015-06-25 35 views
10

Poniższy kod wydaje się działać poprawnie w Clang ++ i GCC:std :: vector na przód zadeklarowanego typu

#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(); 
} 

Gdy człon dane std::vector<A> deklaruje, A jest nadal niekompletna typu. To samo, co przy korzystaniu z std::vector<B> i B zostało zadeklarowane tylko z wyprzedzeniem z class B;. Powinien działać z std::vector, ponieważ zawiera tylko wskaźnik do A.

Czy to gwarantuje działanie lub niezdefiniowane zachowanie?

Odpowiedz

14

Jest to niezdefiniowane zachowanie w C++ 14 i wcześniejszych; dobrze zdefiniowane w C++ 17 (jeśli jest 17).

[res.on.functions]/p2 pocisk 2.7:

W szczególności, efekty nie są zdefiniowane w następujących przypadkach:

  • [...]
  • czy niekompletny typ (3.9) jest używany jako argument szablonu podczas tworzenia instancji komponentu szablonu, chyba że wyraźnie dozwolono dla tego komponentu na .

w C++ 14 i wcześniej, std::vector nie "specjalnie pozwolić" to. Tak więc zachowanie jest niezdefiniowane.

dla C++ 17, N4510 przyjętą w komisji maja 2015 spotkanie, odpręża tę regułę vector, list i forward_list.

1

Zgodnie z sekcją "Parametry szablonu" z cppreference.com może to działać (w zależności od rzeczywistego użycia kontenera) w standardzie C++ 17, ale nie w C++ 14 i wcześniejszych. Prawdopodobnie używasz wersji kompilatorów, które implementują tę część standardu C++ 17.

+0

Faktycznie, papier przyjęty dla C++ 17 został zaakceptowany tylko z 'std :: list',' std :: forward_list' oraz 'std :: vector', dzięki czemu GCC, Clang i MSVC są zgodne po wyjęciu z pudełka . – Morwenn