`std::pmr::monotonic_buffer_resource`:为什么是 `dynamic_cast`?
`std::pmr::monotonic_buffer_resource`: why the `dynamic_cast`?
标准草案 N4618 是这样说的 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)
换句话说,标准不只是比较指针与 this == &rhs
的相等性,而是希望供应商不遗余力地 dynamic_cast
右侧指针。
我想不出任何 理智 情况 dynamic_cast
会改变比较的结果。不过,我能想到一些 疯狂 的情况:
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);
这种差异是否有微妙的原因?如果标准通过删除 dynamic_cast
使 operator==
reflexive/symmetric/transitive 出现什么问题?
这是一个已知缺陷,不过你的问题确实提醒我需要提交正式的问题报告。
this == &other
的简单表述是应该的。 dynamic_cast
是一些样板代码的保留,因此相等的 rhs 不必与 lhs 是同一对象才能被认为是相等的。在最一般的情况下,如果两个 pmr::memory_resource
对象可以互换但没有相同的地址,则必须将 rhs 动态转换为 lhs 的类型以确定是否相等。但是,在pmr::monotonic_buffer_resource
的情况下,需要地址相等,所以dynamic_cast
是多余的。
不过你的 TwoHeadedResource
很聪明。向你致敬,因为你找出了一种会产生影响的情况,即使那不是我们旨在支持的代码类型。 :-)
上有针对此缺陷的官方问题报告
标准草案 N4618 是这样说的 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)
换句话说,标准不只是比较指针与 this == &rhs
的相等性,而是希望供应商不遗余力地 dynamic_cast
右侧指针。
我想不出任何 理智 情况 dynamic_cast
会改变比较的结果。不过,我能想到一些 疯狂 的情况:
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);
这种差异是否有微妙的原因?如果标准通过删除 dynamic_cast
使 operator==
reflexive/symmetric/transitive 出现什么问题?
这是一个已知缺陷,不过你的问题确实提醒我需要提交正式的问题报告。
this == &other
的简单表述是应该的。 dynamic_cast
是一些样板代码的保留,因此相等的 rhs 不必与 lhs 是同一对象才能被认为是相等的。在最一般的情况下,如果两个 pmr::memory_resource
对象可以互换但没有相同的地址,则必须将 rhs 动态转换为 lhs 的类型以确定是否相等。但是,在pmr::monotonic_buffer_resource
的情况下,需要地址相等,所以dynamic_cast
是多余的。
不过你的 TwoHeadedResource
很聪明。向你致敬,因为你找出了一种会产生影响的情况,即使那不是我们旨在支持的代码类型。 :-)