I assume Tiago doesn't propose to break that. He would simply standardize the somewhat-existing practice that we could reasonably put identical functions at identical addresses. (E.g. I know Green Hills' linker has done this for >20 years. But I don't know how Green Hills solves the problem below: whether it turns off the optimization if the address is ever taken, or just lets the behavior be unpredictable at runtime, or what.)
template <int IDENTIFIER>
int TemplateTestFacility_StubClass::method() {
return 0;
}
assert_possibly_true(&method<1> == &method<2>);
Although notice that this is tricky for two reasons. One, the optimizer may cause functions that "look" different to actually have the same behavior after optimization. A classic example is:
template<class T> int distance(T *a, T *b) { return b - a; }
static_assert(&distance<int> != &distance<short>); // must have different codegen, since sizeof(int) != sizeof(short)
assert_possibly_true(&distance<int> == &distance<float>); // can have identical codegen, since sizeof(int) == sizeof(float)
Two, letting the value of (fptr1 == fptr2) be unspecified at compile time means that expressions formerly compile-time-constant are no longer compile-time-constant. For example, today this is legal C++:
int f();
int g();
constexpr bool b = (f == g);
static_assert(b == false);
Making it legal for (f == g) at runtime [that is, "after link-time"] would make the compiler unable to compile this program. We'd have to bite the bullet and add programs like this to Annex C — "used to be valid C++, but no longer." This is totally achievable — after all, this is the very reason why we have an Annex C — but it certainly puts an item in the "Cons" column of our "Pros and Cons" table.
In fact, I guess this brings me full circle back to Brian Bi's point. Consider:
int f();
int g();
template<auto*> struct A {};
A<&f> a;
A<&g> b;
static_assert(!__is_same(decltype(a), decltype(b)));
If `&f == &g`, then this breaks down: Surely `A<value>` must be the same type whenever `value` is the same value! And if `&f` and `&g` have the same value, then `A<&f>` and `A<&g>` must be the same type. But we won't know whether they're the same type until link-time. So... we can't know at compile-time whether these two types are the same or different? That's... not something we can physically represent in C++.
So, to make this idea work at all, we would have to retroactively make it invalid to use the address of a function as a template argument — in the same way it's currently invalid to use the address of a string literal.
But that would almost certainly break someone's code. (Not Brian's example, AFAICT, since he never uses the unique function address as a template argument. But surely it'll break someone's code.)
HTH,
Arthur