¿Por qué se detecta un tipo incompleto en clang dentro de un método de plantilla?

Hoy, encontré un problema de compilación en clang que me sorprendió. Supongo que es razonable, pero me gusta profundizar y escuchar más detalles. Algunas referencias estándar si es posible también.

Tengo una clase con un método de plantilla que se basa en un miembro cuyo tipo no está definido en el encabezado (pero no en la fuente). Algo como lo siguiente:

// Menu.h
class Page;

class Menu
{
public:
    .... // stuff

template<class Visitor>
void VisitWidget( Visitor&& visitor);

private:
std::unique_ptr<Page> m_page; // destructor implemented in source file, so Page is an incomplete type
};

template<class Visitor>
inline void Menu::VisitWidget( Visitor&& visitor);
{
    m_page->Visit( std::forward<Visitor>(visitor) );
}

En VisualStudio, compila. Espero que esto solo se queje al instanciar; tan en línea Sin embargo, en clang, esto no se compila tan pronto como alguien incluye el encabezado. Obligándome a incluir Page.h en Menu.h (que quiero evitar a toda costa).

Me gusta:

// Another.cpp (not Menu.cpp)
#include "Menu.h" // this trigger and error due Page is an incomplete type

incluso si todo el Another.cpp no está usando VisitWidget (incluso en otros encabezados)

Supongo que esto es causado por la línea de alguna manera, ya que el compilador no está obligado a usarlo realmente, pero como hay plantillas en el medio, no estoy tan seguro. ¿Realmente está sonando el tipo?

Respuestas a la pregunta(1)

Su respuesta a la pregunta