我最近知道以下代码格式错误,NDR:
// foo.h
template <typename T>
void foo();
// foo_bar.cpp
template <>
void foo<bar>()
{ /* Implementation for bar */ }
// foo_baz.cpp
template <>
void foo<baz>()
{ /* Implementation for baz */ }
由于foo.h
中未声明专业化。不在foo.h
中声明它们的原因是为了避免#include
使用baz
和bar
的定义(长构建时间(。
显式实例化不会遇到这个问题——不需要在头中声明它们。因此,我考虑使用显式实例化来解决上述问题:
// foo.h
template <typename T>
void foo();
// foo_bar.cpp
template <typename T>
void foo()
{ /* Implementation for bar */ }
template void foo<bar>();
// foo_baz.cpp
template <typename T>
void foo()
{ /* Implementation for baz */ }
template void foo<baz>();
在某种程度上,它将用显式实例化取代专门化。但接下来我的问题来了:假设主模板foo<T>
的两个不同实现是针对不同类型实例化的,那么它们是否违反了ODR?
是的,从技术上讲,这仍然是ODR冲突(假设两个翻译单元中的模板定义不相同(。
对于大多数C++编译器,您可能会逃脱惩罚,但这仍然是一个技术ODR冲突——同一个模板在不同的翻译单元中有不同的定义。
另一方面,如果您将其转换为两个模板专门化(甚至没有定义模板本身(,那么它就不会违反ODR。这就是专用模板的作用。
根据评论的反馈,答案是是,这是ODR违规。
为了解决最初的问题,更好的解决方案是在头中声明模板专用化。为了避免包含依赖项bar
和baz
,转发声明它们就足够了。