不可能快速的C ++代表和不同的翻译单元

时间:2009-10-06 17:14:14

标签: c++ delegates language-lawyer one-definition-rule

根据Sergey Ryazanov的说法,他的Impossibly Fast C++ Delegates无法比较:

  

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

读者回答了哪一个:

  

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

     

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

     

如果您发现MSVC属实,我建议您更新文章(包括比较功能) - 如果MSVC是标准授予,就此而言。

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

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

2 个答案:

答案 0 :(得分:12)

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

因此,可以以一致且可移植的方式在那里定义比较。

答案 1 :(得分:0)

Impossibly Fast C++ Delegates 中所谓的 stub 函数是静态模板成员函数,基本上是 template函数。改进的变体Impossibly Fast C++ Delegates, Fixed也是如此。

所以问题归结为:

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

根据C ++标准(ISO C ++ 17,第17.5.6.1节),答案为

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

换句话说,这种方法符合标准,并且委托可以安全地进行比较-当且仅当将它们绑定到相同的函数并且绑定到相同的对象(如果是成员函数)时,它们的数据才相等。