Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is std::less supposed to allow comparison of unrelated pointers at compile-time?

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:

  1. Its operator() is constexpr.

  2. 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?

like image 582
HolyBlackCat Avatar asked Jun 20 '20 21:06

HolyBlackCat


People also ask

Is it possible to compare two pointers Why?

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.

Can we compare two pointers in C?

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.


1 Answers

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.

like image 192
Brian Bi Avatar answered Oct 05 '22 17:10

Brian Bi