为什么在模板方法中在clang中检测到不完整的类型? [英] Why an incomplete type is detected in clang inside a template method?

查看:326
本文介绍了为什么在模板方法中在clang中检测到不完整的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,我在clang中遇到一个编译问题,让我感到惊讶。我想是合理的,但我想深入了解,听到更多的细节。如果可能的话,还有一些标准引用。



我有一个类的模板方法依赖于一个成员,他的类型是未定义的头部(但不是源) 。像下面这样:

  // Menu.h 
class Page;

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

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

private:
std :: unique_ptr< Page> m_page; // destructor implements 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));
}

在VisualStudio中,它会编译。我期望这只有在抱怨时才会注意;所以内联。但是,在clang,这不会编译,只要有人包括标题。强迫我在Menu.h中包含Page.h(我想不惜一切代价避免)。



喜欢:

  // Another.cpp(not Menu.cpp)
#includeMenu.h//这个触发器和错误页面是一个不完整的类型$ b $即使整个Another.cpp不使用VisitWidget(即使在其他标题中)

$ b $

$ <$ p <$> b

我猜这是由于inline某种原因,因为编译器没有义务真正使用它,但由于中间有模板,我不太确定。是真的clang检查类型吗?

解决方案

是的,这是在MSVC编译,因为它有一个众所周知的错误。它不实现两步模板实例化。



详细说明。 MSVC错误地推迟了模板解析,直到它在代码中被实例化。可能在完整的页面定义变为可见后发生。



但是,标准要求模板在定义的点和所有不依赖于模板参数的类型都被解析。这会失败,因为 m_page 不依赖于访问者参数 - 并且此时它仍然是不完整的类型。



PS 我甚至不能表达我对MSFT这种公然的标准违约(其他人)感到愤怒。当MS兼容代码必须移植到合规的编译器时,它使得跨平台开发变得非常痛苦。


Today, I encountered a compile issue in clang that surprised me. I guess is reasonable but I like to dig deeper and hear more details. Some standard references if possible also.

I have a class with a template method which rely on a member which his type is undefined in the header (but not in the source). Something like the following:

// 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, it compiles. I expect this to only complain when instanciating; so inlining. However, in clang, this doesn't compile as soon as someone includes the header. Forcing me to include Page.h in Menu.h (which I want to avoid at all cost).

Like:

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

even if the whole Another.cpp is not using VisitWidget (even in other headers)

I guess that this is caused by inline somehow, since the compiler is not obligated to really use it, but since there are templates in the middle I am not so sure. Is really clang checking the type?

解决方案

Yes, this compiles in MSVC because it has a well-known bug. It doesn't implement two-step template instantiation.

To elaborate. MSVC wrongly defers template parsing until it is actually instantiated in the code. Likely it happens after full Page definition becomes visible.

However, standard demands that the template is pre-parsed at the point of definition, and all types which are not dependent on template arguments are resolved. This fails, since m_page is not dependent on visitor argument - and it is still incomplete type at this point.

P.S. I can't even express how outraged I am at MSFT for this blatant Standard violation (among others). It makes cross-platform development a real pain, when MS-compliant code has to be ported to conforming compilers.

这篇关于为什么在模板方法中在clang中检测到不完整的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆