Consider this code:
#include <functional> #include <typeinfo> template <typename T> inline constexpr const void *foo = &typeid(T); int main() { constexpr bool a = std::less<const void*>{}(foo<int>, foo<float>); }
Run on gcc.gotbolt.org
If I use <
instead of std::less
here, the code doesn't compile. This is not surprising, because the result of a relational pointer comparsion is unspecified if the pointers point to unrelated objects, and apparently such a comparsion can't be done at compile-time.
<source>:9:20: error: constexpr variable 'a' must be initialized by a constant expression constexpr bool a = foo<int> < foo<float>; ^ ~~~~~~~~~~~~~~~~~~~~~ <source>:9:33: note: comparison has unspecified value constexpr bool a = foo<int> < foo<float>; ^
The code still doesn't compile, even if I use std::less
. The compiler error is the same. std::less
appears to be implemented as <
in at least libstdc++ and libc++; I get the same results on GCC, Clang, and MSVC.
However, the cppreference page about std::less
claims that:
Its operator()
is constexpr
.
It magically implements strict total order on pointers, i.e. can be used to compare unrelated pointers with sensible results.
So, is it a bug in all those compilers, or am I missing some detail about std::less
that makes the code above ill-formed?
When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object types both point to the same object, or both point one past the last element of the same array object, they compare equal.
We can compare pointers if they are pointing to the same array. Relational pointers can be used to compare two pointers. Pointers can't be multiplied or divided.
I don't think there's a clear answer to the question that you're asking. This is a specific case of LWG 2833: marking a library function constexpr
does not explain the circumstances under which calling the function will yield a constant expression.
Until this issue is resolved, I think you simply cannot rely on std::less
being able to compare unrelated pointers at compile time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With