-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
Currently the default constructor of error_category lacks constexpr in MSVC STL, which is non-conforming and expected to be fixed in vNext (see #1116).
Lines 70 to 72 in 2f03bdf
| /* constexpr */ error_category() noexcept { // TRANSITION, ABI | |
| _Addr = reinterpret_cast<uintptr_t>(this); | |
| } |
However, it seems that we can implement _Addr as a union so that it can be constant during constant evaluation like this:
class ErrorCategoryLike {
private:
union AddrStorage {
private:
uintptr_t num;
ErrorCategoryLike* ptr;
public:
constexpr explicit AddrStorage(uintptr_t addr_num) noexcept : num(addr_num) {}
constexpr explicit AddrStorage(ErrorCategoryLike* addr_ptr) noexcept : ptr(addr_ptr) {}
};
static_assert(sizeof(AddrStorage) == sizeof(uintptr_t) && alignof(AddrStorage) == alignof(uintptr_t),
"Unsupported platform");
AddrStorage addr;
protected:
constexpr explicit ErrorCategoryLike(uintptr_t addr_num) noexcept : addr(addr_num) {}
public:
constexpr ErrorCategoryLike() noexcept : addr(this) {}
bool operator==(const ErrorCategoryLike& rhs) const noexcept {
return _STD _Bit_cast<uintptr_t>(addr) == _STD _Bit_cast<uintptr_t>(rhs.addr);
}
virtual ~ErrorCategoryLike() = default;
};See also the test on godbolt.
Such technique requires that
- the union has the same size and alignment of
uintptr_t, and reinterpret_castbetweenuintptr_tand pointers is equivalent tobit_cast.
I think both conditions hold on Windows (at least for MSVC, clang-cl, etc.) although they are not guaranteed by the standard.
So I guess we can add the constexpr without ABI breakge. Is it right?
Line 112 in 2f03bdf
| constexpr explicit error_category(const uintptr_t _Addr_) noexcept : _Addr(_Addr_) {} |
BTW, this protected constructor is probably also non-conforming as it is probably observable by a conforming program (that defines a class derived from error_category and tests the non-existence of this constructor). Changing its access control or signature seemly breaks ABI.