25

The C++ standard says the following about the equality operator ==:

[C++11: 5.10/1]: [..] Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address.

My initial interpretation was that functions don't semantically have "addresses" per se at this level, and that therefore the "or both represent the same address" could only be intended to refer to objects, and not functions. Otherwise why bother with the "point to the same function" clause?

That is, two function pointers of the same type compare equal if and only if both point to the same function, period.

The consequence of this would be that the behaviour witnessed in this question (pointers to two distinct but identical functions have identical values) would be an implementation bug, since pointers to distinct functions would be required to be unique.

I feel that this is the intent of the clause, but I can't find a way to objectively defend the viewpoint that this is how the passage's meaning should actually be inferred, or that it really was the intent of the committee, and now my interpretation has come into question:

[D]iscuss with me how "[...] or both represent the same address." is not being satisfied by Visual C++'s behavior. (@jstine)

So my question is about the intent of this standard passage.

Either:

  • I am on the right track: function pointers must compare equal iff they both point to the same function ("addresses" be damned), or

  • There is a redundancy in the passage: function pointers must compare equal iff they both point to the same function or both represent the same address; and, by extension, an implementation is allowed to make two functions exist at the same address.

Which is it?

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055

1 Answers1

5

Well, look at the statement logically. You have three clauses:

  1. Both are null.

  2. Both point to the same function.

  3. Both have the same address.

These clauses are joined by a logical "or". Therefore, if any one of these is true, then the two pointers are allowed to compare equal. If a compiler so decides, it is possible to fail #3 yet still pass #2. Logical "or" means that such pointers would compare equal.

Also, it should be noted that member pointers do not have an "address" in the traditional sense. They do have a value, but it's not a memory address. That's why you're not allowed to cast them to void* and so forth.

The passage guarantees, given function pointers t and u, if t == u, that t(...); shall cause the same behavior as u(...);. That behavior will either be referencing NULL, calling the same function, or executing the code at the same address. Thus, the same behavior is had.

Technically, Mehrdad's problem is that he's getting the same value from two different member function names. So #3 applies. I don't see anything in the standard that requires that different member function names return distinct values when getting functions for them.

Community
  • 1
  • 1
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • I am a bit confused: how can it fail #3 (they point to different addresses) and pass #2 (they point to the same fxn)? if i convert them both to void*, they will have different values and compare different, while before conversion to void* they compared equal. is this possible? – Andy Prowl Jan 07 '13 at 02:41
  • @AndyProwl: There's no rule in the spec that two pointers equal will be equal after conversion to void*. Nor does it say that two unequal pointers will be unequal after such a conversion. – Nicol Bolas Jan 07 '13 at 03:02
  • but if i read correctly between the lines, it mandates that conversion from void* back to the original type yields the original value. but the same void* value could not convert into two different values of the same original type – Andy Prowl Jan 07 '13 at 03:13
  • (i am referring to 5.2.9/13 and 5.2.10/8) - just want to understand. all of this sounds confusing to me. i'd just expect different functions to have different addresses *as long as the program seems to care* – Andy Prowl Jan 07 '13 at 03:19
  • @AndyProwl: As far as this particular statement is concerned, equality can be determined without the addresses being equal. Whether other statements effectively force them to be equal is another matter. – Nicol Bolas Jan 07 '13 at 03:44
  • This answer seems like a valid (and particularly straightforward) interpretation, though you haven't addressed my question regarding what the intention of the standard wording is likely to be... in particular w.r.t. a redundancy between #2 and #3... – Lightness Races in Orbit Jan 07 '13 at 04:08
  • 2
    #3 happening but #2 not happening could easily be the result of a specialization optimization, where the same logical function is compiled to two different implementations that were called depending on different static guarantees at the call site, in which case the compiler could record extra data somewhere to ensure that function pointers still compared equal despite having different addresses (the pointer might contain more than an address, for example, or some extra table might be used). I don't know if any mainstream compilers do that in practice, but there's no reason to forbid it. – Stephen Lin Mar 02 '13 at 02:33