Warum wird ein unvollständiger Typ in einer Template-Methode erkannt?

Heute bin ich auf ein Kompilierungsproblem in Clang gestoßen, das mich überrascht hat. Ich denke, es ist vernünftig, aber ich mag es, tiefer zu graben und mehr Details zu hören. Einige Standardreferenzen wenn möglich auch.

Ich habe eine Klasse mit einer Template-Methode, die auf einem Member basiert, dessen Typ im Header undefiniert ist (aber nicht in der Quelle). So etwas wie das folgende:

// 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) );
}

In VisualStudio wird es kompiliert. Ich erwarte, dass sich das nur beim Anstoßen beschwert; so inlining. In clang wird dies jedoch nicht kompiliert, sobald jemand den Header enthält. Ich muss Page.h in Menu.h aufnehmen (was ich unbedingt vermeiden möchte).

Mögen

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

auch wenn die gesamte Another.cpp VisitWidget nicht benutzt (auch nicht in anderen Headern)

Ich vermute, dass dies irgendwie durch Inline verursacht wird, da der Compiler nicht verpflichtet ist, es wirklich zu benutzen, aber da es Vorlagen in der Mitte gibt, bin ich mir nicht so sicher. Prüft Clang wirklich den Typ?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage