如果在不同类型的多个翻译单元中定义模板,则违反ODR



我最近知道以下代码格式错误,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使用bazbar的定义(长构建时间(。

显式实例化不会遇到这个问题——不需要在头中声明它们。因此,我考虑使用显式实例化来解决上述问题:

// 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违规。

为了解决最初的问题,更好的解决方案是在头中声明模板专用化。为了避免包含依赖项barbaz,转发声明它们就足够了。

相关内容

  • 没有找到相关文章