Visual Studio 2008 在编译模板时不关心基类的存在?
Posted
技术标签:
【中文标题】Visual Studio 2008 在编译模板时不关心基类的存在?【英文标题】:Visual Studio 2008 does not care about base class existence when compiling templates? 【发布时间】:2011-03-04 19:08:51 【问题描述】:似乎 VS 2008 处理类模板的继承与其他编译器有点不同。 以下代码在 VS 2008 上编译没有任何错误(使用默认选项):
template <typename S, typename T>
class someclass : public non_existent_class
T operator() (S s) const
return T(s);
;
问题是,为什么?由于未定义标识符non_existent_class
,没有其他编译器能够做到这一点(尝试过 GCC 4.5.0、Intel、Online Comeau、VS 2005)。也许是新的 C++0x 标准中的某些东西证明了这种行为的合理性?
【问题讨论】:
【参考方案1】:这很可能是由于 Visual Studio 在应该执行两阶段时执行单阶段名称查找这一事实的结果。非依赖名称“non_existent_class”应该在第一阶段失败,无论模板是否被实例化,都会发生在定义点。
这是一个错误,但在 MS 从根本上改变他们的编译器对模板的工作方式之前,它永远不会被修复。
http://womble.decadent.org.uk/c++/template-faq.html#two-phase
http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html
【讨论】:
【参考方案2】:Visual Studio 的编译器从不以符合标准而闻名。这一定是另一个错误,如果你报告它,他们会告诉你他们有更重要的事情要做。不用说,一旦你实例化了这个类,编译器就会报错。
是的,编译器在实例化之前无法诊断出某些事情。这不在他们的计数之内,编译器必须发出诊断。 C++0x 没有改变这个规则
【讨论】:
VS 2005 拒绝编译这个。必须是一些新功能来加快模板繁重代码的编译速度。【参考方案3】:当您说编译器接受该代码而其他编译器不接受时,您是指使用那段代码还是实例化模板?
在遇到定义时不会编译模板,而是在实例化它们时编译。如果您没有实例化模板,则编译器可能会完全忽略整个模板定义(尽可能多地,因为它需要能够解释足够多的代码才能知道模板定义何时完成)。
然后在稍后的阶段,如果模板实际被实例化,并且假设模板没有专门化,编译器会报错。请注意,如果您为特定类型提供特化,则该特化不需要继承自同一个不存在的类。
在这种特殊情况下,我倾向于认为这是由于 Microsoft 编译器对依赖名称所做的特殊处理(如在非标准中)。与您不需要在模板内的依赖名称前指定 typename
相同的方式(考虑一个基类,或具有此模板的类型参数的不同模板的实例化),编译器可能正在考虑在实际实例化发生之前定义基类,并等待那一刻执行验证。
【讨论】:
只有这个代码。实例化时会失败。实际上,您对验证是绝对正确的,在哪里定义基类并不重要。可能和 C++0x 的“外部模板”特性有关? 不完全正确。在第一遍中,只允许从属名称保持未解析。此示例不符合条件。 @Surovov Victor:extern template
不是即将发布的标准的一部分(它在当前标准中,但仅由一家编译器制造商实施,同一供应商推动从标准中删除)
David R. 你错了。 export 模板在标准中,将被删除,因为只有一个编译器实现了它,extern 模板是 C++0x 的一个新特性,用于防止编译器在遇到时实例化模板
@Crazy 标准允许编译器接受任何和所有模板定义——在解析/分析模板时,即使是非依赖名称也不必给出错误。只有在实例化时,才需要进行诊断。如果在此之前提供了诊断,则说明实施质量良好。以上是关于Visual Studio 2008 在编译模板时不关心基类的存在?的主要内容,如果未能解决你的问题,请参考以下文章
在 Visual Studio 2008 中将 Fxcop 错误显示为编译错误
使用 Visual Studio 2008 编译和运行 MFC 应用程序?
我可以在 Visual Studio 2008 中使用 Visual Studio 6 编译的 C++ 静态库吗?
如何在visual studio2008中创建,编译和运行C++程序,