为什么在标题上的结构中声明的模板不违反 ODR 并且专用化会违反 ODR

Why templates declared in the struct on the header dont violate ODR and specialization does?

本文关键字:ODR 专用 标题 结构 声明 为什么      更新时间:2023-10-16

我有这个代码:

#include <iostream>
struct A
{
    template<typename T> bool isImplemented()
    {
                std::cout << "Not Implemented" << std::endl;
                return false;
    }
};
template<> inline bool A::isImplemented<int>()
{
    std::cout << "int Implemented" << std::endl;
    return true;
}

我可以理解为什么模板专用化需要内联,为了防止违反 ODR,内联将合并转换表以避免冲突。

但是,为什么我不需要在结构 A 内部实现的内联?也许这个问题可以扩展到,为什么如果该方法是在标头上的结构/类内声明的,它不需要内联?据我所知,它会在调用的每个对象文件 (.o( 上创建符号,违反了 ODR,为什么没有发生这种情况?

您不需要它有两个原因:

  • 在类的定义中定义的每个函数都是隐式的inline
  • 模板不需要inline关键字。请记住,您的原始函数是模板,而专业化不是。

这里要强调的一点是template<typename T> bool isImplemented()不是一个函数。它是函数的模板,只有在专用后才会存在(作为代码(,就像您对template<> inline bool A::isImplemented<int>()所做的那样。

此处的inline不是强制性的。程序在没有它的情况下可以完美编译和运行。

奇怪的是,您的struct A不依赖于任何模板参数,也不依赖于isImplemented()方法,所以我仍在尝试弄清楚您的意图。

函数的简单用法可能如下所示:

int  main( )
{
    A a;
    a.isImplemented< int >( );
    a.isImplemented< double >( );
}

和输出:

int Implemented
Not Implemented

基本上,您可以从通用的专业化中分辨出您明确实现的专业化。这是你需要的吗?

编辑:

鉴于对我的回答的评论,我相信原始问题在这里得到了很好的回答:

  • 非命名空间范围内的显式专用化
  • 模板类中模板函数的显式专用化C++语法?