É verdade que uma declaração unique_ptr, diferentemente de uma declaração auto_ptr, é bem definida quando seu tipo de template é de um tipo incompleto?

eu escreviEste artigo e recebi alguns comentários que me confundiram.

Basicamente se resume a ter vistoT2 usado apenas como um parâmetro modelo e erroneamente saltou para a conclusão de que eu poderia, portanto, aproveitar a oportunidade de declaração para a frente:

struct T2;

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

Isso invoca o UB se eu não continuar a definirT2 em algum lugar na mesma TU, porquestd::auto_ptr<T2> chamadasdelete em seu internoT2*echamandodelete em um ponteiro para um objeto de um tipo incompleto cujo tipo completo tem um destruidor não-trivial é indefinido:

[C++11: 5.3.5/5]: Se o objeto que está sendo excluído tiver um tipo de classe incompleto no ponto de exclusão e a classe completa tiver um destruidor não-trivial ou uma função de desalocação, o comportamento será indefinido.

O toolchain do GCC que estava usando - v4.3.3 (Sourcery G ++ Lite 2009q1-203) - teve a gentileza de me informar com uma nota:

Nota: nem o destruidor nem a exclusão do operador específico da classe serão chamados, mesmo que sejam declarados quando a classe é definida.

embora pareça difícil obter esse diagnóstico em outras versões do GCC.

Minha queixa era que seria muito mais fácil detectar um bug como este sedeleteUm ponteiro para uma instância de um tipo incompletomal formado em vez de UB, mas isso parece ser um problema intratável para uma implementação resolver, então eu entendo porque é UB.

Mas então me disseram que, se eu usassestd::unique_ptr<T2> em vez disso, isso seria seguro e compatível.

n3035 supostamente diz em 20.9.10.2:

O parâmetro do modeloT dounique_ptr pode ser um tipo incompleto.

Tudo o que posso encontrar no C ++ 11 é:

[C++11: 20.7.1.1.1]:

/ 1 O modelo de turmadefault_delete serve como deleter padrão (política de destruição) para o modelo de classeunique_ptr.

/ 2 O parâmetro do modeloT dodefault_delete pode ser um tipo incompleto.

Mas,default_delete'soperator() requer um tipo completo:

[C++11: 20.7.1.1.2/4]: E seT é um tipo incompleto, o programa está mal formado.

Eu suponho que minha pergunta é esta:

Os comentadores do meu artigo estão corretos ao dizer que um bloco de tradução que consiste apenas no seguinte código é bem formado e bem definido? Ou eles estão errados?

struct T2;

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

Se eles estão corretos, como é esperado que um compilador implemente isso, dado que existem boas razões para ser UB, pelo menos quando umstd::auto_ptr é usado?

questionAnswers(2)

yourAnswerToTheQuestion