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?