Por que um tipo incompleto é detectado no clang dentro de um método de modelo?
Hoje, encontrei um problema de compilação no clang que me surpreendeu. Eu acho que é razoável, mas eu gosto de ir mais fundo e ouvir mais detalhes. Algumas referências padrão, se possível também.
Eu tenho uma classe com um método de modelo que depende de um membro cujo tipo é indefinido no cabeçalho (mas não na fonte). Algo como o seguinte:
// 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) );
}
No VisualStudio, ele compila. Eu espero que isso só reclame ao instanciar; tão inlining. No entanto, no clang, isso não é compilado assim que alguém inclui o cabeçalho. Forçando-me a incluir Page.h no Menu.h (que eu quero evitar a todo custo).
Gostar:
// Another.cpp (not Menu.cpp)
#include "Menu.h" // this trigger and error due Page is an incomplete type
mesmo que o Another.cpp inteiro não esteja usando o VisitWidget (mesmo em outros cabeçalhos)
Eu acho que isso é causado pelo inline de alguma forma, já que o compilador não é obrigado a realmente usá-lo, mas como existem modelos no meio, não tenho tanta certeza. O clang está realmente checando o tipo?