据谢尔盖·梁赞诺夫说,他的 快得难以置信的 C++ 委托 没有可比性:

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

读者对此的回复是:

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

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

如果您发现 MSVC 也是如此(如果 MSVC 在这方面是标准授予的),我会敦促您更新本文(包括比较能力)。

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

C++ 标准是否明确禁止此类使用?如果是,最近的编译器是否在这方面实际上符合标准?

有帮助吗?

解决方案

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

因此,比较可以很好地在有一个符合的和便携的方式来定义。

其他提示

所谓的 存根 功能于 快得难以置信的 C++ 委托静态模板成员函数, ,这基本上是 模板函数. 。这同样适用于改进型 难以置信的快速 C++ 委托,已修复.

所以问题归结为:

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top