Czy to prawda, że ​​deklaracja unique_ptr, w przeciwieństwie do deklaracji auto_ptr, jest dobrze zdefiniowana, gdy jej typ szablonu jest niekompletny?

napisałemTen artykuł i dostałem kilka komentarzy, które mnie zdezorientowały.

Zasadniczo sprowadza się to do tego, że widziałemT2 używany tylko jako parametr szablonu i omyłkowo przeskoczył do wniosku, że mogę zatem skorzystać z możliwości przekazania deklaracji:

struct T2;

struct T1
{
    std::auto_ptr<T2> obj;
};

To wywołuje UB, jeśli nie będę definiowaćT2 gdzieś w tej samej TU, ponieważstd::auto_ptr<T2> połączeniadelete na swoim wewnętrznymT2*, ipowołaniedelete na wskaźniku do obiektu niekompletnego typu, którego typ kompletny ma nietrywialny destruktor, jest niezdefiniowany:

[C++11: 5.3.5/5]: Jeśli usuwany obiekt ma niekompletny typ klasy w miejscu usunięcia, a pełna klasa ma nietrywialny destruktor lub funkcję zwolnienia, zachowanie jest niezdefiniowane.

Zestaw narzędzi GCC, z którego korzystałem - wersja 4.3.3 (Sourcery G ++ Lite 2009q1-203) - był na tyle uprzejmy, że dał mi znać:

Uwaga: nie zostanie wywołany ani destruktor, ani operator usuwania specyficzny dla klasy, nawet jeśli są zadeklarowane, gdy klasa jest zdefiniowana.

choć wydaje się, że trudno jest uzyskać tę diagnostykę w innych wersjach GCC.

Narzekałem, że o wiele łatwiej byłoby wykryć taki błąd, jeślideleteWstawiono wskaźnik do instancji niekompletnego typuźle uformowany zamiast UB, ale wydaje się, że problem jest trudny do rozwiązania, więc rozumiem, dlaczego to jest UB.

Ale wtedy mi to powiedziano, gdybym miał użyćstd::unique_ptr<T2> zamiast tego byłoby to bezpieczne i zgodne.

n3035 rzekomo mówi o 20.9.10.2:

Parametr szablonuT zunique_ptr może być niekompletny.

Wszystko, co mogę znaleźć w C ++ 11, to:

[C++11: 20.7.1.1.1]:

/ 1 Szablon klasydefault_delete służy jako domyślny deleter (polityka niszczenia) dla szablonu klasyunique_ptr.

/ 2 Parametr szablonuT zdefault_delete może być niekompletny.

Ale,default_deletejestoperator() nie wymaga pełnego typu:

[C++11: 20.7.1.1.2/4]: JeśliT jest niekompletnym typem, program jest źle sformatowany.

Przypuszczam, że moje pytanie brzmi:

Czy komentatorzy mojego artykułu mają rację mówiąc, że jednostka tłumaczeniowa składająca się tylko z następującego kodu jest dobrze uformowana i dobrze zdefiniowana? Czy oni się mylą?

struct T2;

struct T1
{
    std::unique_ptr<T2> obj;
};

Jeśli są poprawne, w jaki sposób kompilator ma to zaimplementować, biorąc pod uwagę, że istnieją dobre powody, dla których jest to UB, przynajmniej wtedy, gdystd::auto_ptr jest używany?

questionAnswers(2)

yourAnswerToTheQuestion