19

根据 Sergey Ryazanov 的说法,他的Impossibly Fast C++ Delegates没有可比性:

我的代表无法比较。未定义比较运算符,因为委托不包含指向方法的指针。指向存根函数的指针在不同的编译单元中可能不同。

读者回复了哪一位:

“指向存根函数的指针在不同的编译单元中可能不同。” AFAIK,这不是真的。编译器需要重用在不同编译单元中生成的模板函数(我确信这一点——但我认为 Borland 曾经违反过这条规则)。我认为这是因为类(不在“无名”命名空间中的类)使用外部链接,并且您使用存根函数的方式将始终阻止它们被内联(尽管这不应该成为获取函数地址的问题将强制生成一个非内联版本,并且链接器执行的“外部链接”将消除除一个类似命名的函数之外的所有函数(标准假定并要求它们相同))...

如果您在一个翻译单元(cpp 文件)中定义模板函数,然后在另一个翻译单元中以不同方式定义相同的函数,则只有两个版本中的一个会使其成为最终的可执行文件。(这实际上违反了“一个定义规则”,但适用于 GCC,至少......不确定 MSVC。)关键是:[存根的]地址在不同的单元中是相同的。

如果您发现这对于 MSVC 是正确的,我会敦促您更新文章(包括比较功能) - 如果 MSVC 是标准授予,在这方面。

现在这篇文章已经四年了,作者在过去三年左右没有回复任何评论,所以我想知道上述评论是否有任何优点,是否确实可以将这个具体实现更改为支持对比。

C++ 标准是否明确禁止这种用法,如果是,那么最近的编译器在这方面是否真正符合标准?

4

2 回答 2

12

该代码既符合标准,也很好。我没有看到他违反 ODR 的任何地方,并且具有相同模板参数的函数模板的所有实例化确实应该具有“相同的地址”(从某种意义上说,指向函数的指针应该都是相等的) - 如何这是否实现并不重要。ISO C++03 14.5.5.1[temp.over.link] 更详细地描述了这些规则。

因此,可以以一致且可移植的方式很好地定义比较。

于 2009-10-06T17:28:18.530 回答
1

Impossibly Fast C++ Delegates中所谓的stub函数是静态模板成员函数,基本上就是模板函数。这同样适用于改进的变体Impossibly Fast C++ Delegates, Fixed

所以问题归结为:

不同翻译单元中模板函数的实例化(使用相同的模板参数和定义)是否共享相同的函数指针地址?

根据 C++ 标准(ISO C++17, § 17.5.6.1),答案是肯定的。

正如@Pavel 在他的回答中所说,这同样适用于 ISO C++03 标准(ISO C++03,第 14.5.5.1 节)。

换句话说,这种方法符合标准并且委托是安全的可比较的——当且仅当它们绑定到相同的函数和(在成员函数的情况下)相同的对象时,它们的数据比较相等。

于 2019-03-31T13:32:48.290 回答