我应该声明我的函数模板专业化还是定义它们就足够了?

2024-05-02

我有一些课程可以检查。实现此功能的代码在头文件中声明一个函数模板,并将其专门用于不同的源文件:

// check.h
template <class T>
bool check(const T& object);
// class1.h
struct Class1 {int mass;};
// check_class1.cpp
#include "class1.h"
#include "check.h"
template <>
bool check(const Class1& object) {return object.mass < 100;}
// class2.h
struct Class2 {int price;};
// check_class2.cpp
#include "class2.h"
#include "check.h"
template <>
bool check(const Class2& object) {return object.price < 1000;}
// class3.h
struct Class3 {int x;};
... // 10 more classes which I can check

这段代码的使用方式如下:

#include "class1.h"
#include "class2.h"
#include "class3.h"
#include "check.h"

int main()
{
    Class1 object1{50};
    Class2 object2{500};
    Class3 object3{8};
    check(object1); // OK
    check(object2); // OK
    check(object3); // a link error appears here
}

这效果非常好。当我添加另一个班级时Class3我可以检查,我不需要触及头文件,因为它定义了一个非常广泛的接口。如果我忘记实施check函数为Class3,链接器会用错误消息提醒我。

我的问题是:这种行为是否有保证,或者我的代码是否幸运?我正在使用 Visual Studio。

如果我想专门化我的函数模板,我是否应该在头文件中声明我的所有专门化?


为了安全起见,我会添加这些声明(好吧,假设我不会因为任何原因而超载)。我认为法律对此并不太明确。其一,我们有

[温度解释规范]

6 https://timsong-cpp.github.io/cppwp/n4659/temp.expl.spec#6如果是模板、成员模板或类的成员 模板是明确专门化的,那么该专门化应该是 在第一次使用该专业化之前声明,这会导致 在每个翻译单元中发生隐式实例化 发生这种使用的情况;无需诊断。如果程序 没有提供显式专业化的定义,并且 要么专业化的使用方式会导致 要进行隐式实例化或者该成员是虚拟成员 函数,程序格式错误,无需诊断。一个 永远不会为显式实例化生成隐式实例化 已声明但未定义的专业化。

如果我没读错的话,这意味着如果将显式专业化添加到main.cpp,那么必然会出现before main。因为那是可能发生隐式实例化的地方。该段落不会使您的代码变成格式错误的 NDR,因为用法和显式专业化出现在不同的 TU 中。但这确实引起了人们的担忧。

另一方面,还有这样一段话:

[temp]

7 https://timsong-cpp.github.io/cppwp/n4659/temp#7函数模板、类模板的成员函数、 变量模板或类模板的静态数据成员应为 在每个隐含的翻译单元中定义 实例化,除非明确相应的专业化 在某个翻译单元中实例化;无需诊断。

这允许我们明确地实例化在单独的看不见的 TU 中。但它不提供明确的专业化津贴。至于这是有意为之还是疏忽,我不能说。

它起作用的原因可能是由于整个事情的实施方式。当函数声明被隐式实例化时,它会生成一个符号,该符号恰好与显式特化生成的符号相匹配。匹配的符号意味着一个快乐的链接器,因此一切都会构建并运行。

但从语言律师的角度来看,我认为我们可以称这里的行为为未定义的遗漏。它是未定义的,只是因为标准没有解决它。因此,回到我的开场白,为了安全起见,我会添加它们,因为至少标准会解决放置问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我应该声明我的函数模板专业化还是定义它们就足够了? 的相关文章

随机推荐