There are so many questions on ODR but I cannot find what I'm looking for, so apologies if this a duplicate or if the title is inappropriate.
Consider the following:
struct t {t(*id)();};
template<typename T>
t type() {return {type<T>};}
This is an over-simplification of my attempt to define a unique identifier per type, that hopefully remains unique across different compilation units.
In particular, given a concrete type T
like std::string
, and assuming two distinct compilation units include the above code in a header file, I would like expression
type<T>().id
to take the same value (of type t(*)()
) in both units, hence serve as a unique identifier for type T
.
The value is the address of function type<T>
, so the question is whether a unique function type<T>
in the program is guaranteed by the one-definition rule. iso 3.2/3 says
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program.
where by 3.2/2
A non-overloaded function whose name appears as a potentially-evaluated expression or [...], is odr-used, unless [...]
and I assume a function is non-inline if its address is taken (though I can't find that in the standard).
iso 3.2/5 lists a number of exceptions, but the only references to functions are
inline function with external linkage, [...], non-static function template, [...], member function of a class template, or template specialization for which some template parameters are not specified [...]
and none appears to be the case here.
A verifiable example would take more than one file. In fact, an example claimed to fail is given by Dieter Lücking, though it does not fail in my case (which I do not take as any form of "guarantee").
So, is this going to work or not?