`std::pmr::monotonic_buffer_resource`: why the `dynamic_cast`?

Viewed 858

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?

1 Answers
Related