考虑这两个功能:
void foo() {}
void bar() {}
是否保证&foo != &bar
?
类似地,
template<class T> void foo() { }
是否保证&foo<int> != &foo<double>
?
我知道折叠函数定义有两个连接符。
MSVC积极地COMDAT折叠函数,因此具有相同实现的两个函数可以转换为一个函数。作为副作用,这两个函数共享相同的地址。我的印象是这是非法的,但我无法找到标准中的哪些内容是非法的。
The Gold linker也会折叠功能,同时设置为safe
和all
。 safe
表示如果采用功能地址,则不会折叠,而all
即使采用地址也会折叠。因此,如果函数具有不同的地址,则gold的折叠safe
表现为。
虽然折叠可能是意料之外的,并且存在依赖于具有不同地址的不同(相同实现)函数的代码(因此折叠可能是危险的),但在当前的C ++标准下它实际上是非法的吗? (此时为C ++ 14)(自然如果safe
折叠是合法的)
答案 0 :(得分:11)
是。从标准(§5.10/ 1):“两个相同的指针 类型比较等于当且仅当它们都为空时,两者都是点 相同的功能,或两者代表相同的地址“
实例化后,foo<int>
和foo<double>
是两个不同的功能,因此上述内容也适用于它们。
答案 1 :(得分:7)
因此,有问题的部分显然是或两者都代表相同的地址(3.9.2)。
IMO这部分显然是为了定义对象指针类型的语义。仅适用于对象指针类型。
短语引用第3.9.2节,这意味着我们应该看一下。 3.9.2关于对象指针所代表的地址的讨论(以及其他)。它没有谈论函数指针所代表的地址。其中,国际海事组织只留下两种可能的解释:
1)这个短语根本不适用于函数指针。这只剩下两个空指针和两个指向同一函数的指针,比较相等,这可能是我们大多数人所期望的。
2)这句话确实适用。由于它引用了3.9.2,它没有说明函数指针所代表的地址,我们可以使任何两个函数指针进行比较相等。这是非常意外的,当然渲染比较函数指针是完全没用的。
所以,虽然从技术上来说可以说明(2)是有效的解释,IMO它不是有意义的解释,因此应该被忽视。既然不是每个人似乎都同意这一点,我也认为需要对标准进行澄清。
答案 2 :(得分:3)
5.10平等运算符
[expr.eq]
1
==
(等于)和!=
(不等于)运算符组从左到右。操作数应具有算术,枚举,指针或指向成员类型的指针,或者键入std::nullptr_t
。运算符==
和!=
都会生成true
或false
,即bool
类型的结果。在下面的每种情况下,操作数在应用指定的转换后应具有相同的类型。
2 如果至少有一个操作数是指针,则在两个操作数上执行指针转换(4.10)和限定转换(4.4)以将它们带到它们的复合指针类型(第5节)。比较指针定义如下:两个指针比较相等,如果它们都是空的,都指向相同的函数,或者两者都代表相同的地址(3.9.2),否则它们比较不相等。
让我们采取最后一点比特:
inline
函数的外联版本可能会使用其地址,除非你想使函数指针比较过于复杂和昂贵。if and only if
简化为简单的if
会让其解释,但明确授权使任何两个函数相同,只要它否则不会改变符合要求的程序的可观察行为。