The draft standard N4618 says this about std::pmr::monotonic_buffer_resource:
bool do_is_equal(const memory_resource& other) const noexcept override;Returns:
this == dynamic_cast<const monotonic_buffer_resource*>(&other)
In other words, rather than just comparing the pointers for equality with this == &rhs, the Standard wants the vendor to go out of their way to dynamic_cast the right-hand pointer.
I can't think of any sane situation in which the dynamic_cast would change the outcome of the comparison. I can think of some insane cases, though:
class new_delete_memory_resource : public memory_resource {
void *do_allocate(size_t bytes, size_t align) override {
return ::operator new(bytes, align);
}
void *do_deallocate(void *p, size_t bytes, size_t align) override {
::operator delete(p, bytes, align);
}
bool do_is_equal(const memory_resource& rhs) const noexcept override {
return (this == &rhs);
}
};
class TwoHeadedResource :
public new_delete_memory_resource,
public monotonic_buffer_resource
{
};
TwoHeadedResource thr;
memory_resource *a = static_cast<new_delete_memory_resource *>(thr);
memory_resource *b = static_cast<monotonic_buffer_resource *>(thr);
assert(*a != *b);
assert(*b == *a);
Is there a subtle reason for this discrepancy? What would have gone wrong if the Standard had made operator== reflexive/symmetric/transitive by removing the dynamic_cast?
This is a known defect, though your question does remind me that I need to file a formal issue report.
The simple formulation of this == &other is what it should be. The dynamic_cast is a hold-over from some boilerplate code whereby the rhs of the equality does not have to be the same object as the lhs in order to be considered equal. In the most general case, if two pmr::memory_resource objects are interchangeable but don't have the same address, you'll have to dynamically cast the rhs to the type of the lhs in order to determine equality. However, in the case of pmr::monotonic_buffer_resource, address equality is required, so the dynamic_cast is superfluous.
Your TwoHeadedResource is clever, though. Hats off to you for figuring out a situation where it would make a difference, even though that is not the type of code we aim to support. :-)
EDIT: There is now an official issue report for this defect at http://cplusplus.github.io/LWG/lwg-active.html#3000.
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