dma*_*ola 3 c++ templates smart-pointers clang c++11
今天,我在clang中遇到了一个让我感到惊讶的编译问题.我想是合理的,但我喜欢深入挖掘并听到更多细节.如果可能,还有一些标准参考.
我有一个带有模板方法的类,它依赖于一个成员,它的类型在头文件中未定义(但不在源代码中).类似于以下内容:
// 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) );
}
Run Code Online (Sandbox Code Playgroud)
在VisualStudio中,它编译.我希望这只会在实施时抱怨; 如此内联.但是,在clang中,只要有人包含标题,就不会编译.强迫我在Menu.h中包含Page.h(我想不惜一切代价避免使用它).
喜欢:
// Another.cpp (not Menu.cpp)
#include "Menu.h" // this trigger and error due Page is an incomplete type
Run Code Online (Sandbox Code Playgroud)
即使整个Another.cpp没有使用VisitWidget(即使在其他标题中)
我猜这是由内联引起的某种方式,因为编译器没有义务真正使用它,但由于中间有模板,我不太确定.是真的铿锵检查类型?
是的,这在MSVC中编译,因为它有一个众所周知的bug.它不实现两步模板实例化.
详细说明.MSVC错误地推迟了模板解析,直到它在代码中实际实例化为止.可能在完全Page定义变得可见之后发生.
但是,标准要求在定义点预解析模板,并且解析所有不依赖于模板参数的类型.这失败了,因为m_page它不依赖于访问者参数 - 而且此时它仍然是不完整的类型.
PS我甚至无法表达我对MSFT这种明显的标准违规(以及其他)的愤怒.当符合MS的代码必须被移植到符合编译器时,它使跨平台开发变得非常痛苦.
| 归档时间: |
|
| 查看次数: |
342 次 |
| 最近记录: |