2个问题:
以下代码的格式是否符合定义的行为?
是否有任何可能的 C++ 实现可以断言?
代码(c++11 及更高版本):
#include <cassert>
#include <utility>
#include <ciso646>
template<class T>
auto to_address(T* p) { return reinterpret_cast<unsigned char const*>(p); }
/// Test whether part is a sub-object of object
template<class Object, class Part>
bool is_within_object(Object& object, Part& part)
{
auto first = to_address(std::addressof(object)),
last = first + sizeof(Object);
auto p = to_address(std::addressof(part));
return (first <= p) and (p < last);
}
struct X
{
int a = 0;
int& get_a() { return a; }
int& get_b() { return b; }
private:
int b = 0;
};
int main()
{
X x;
assert(is_within_object(x, x.get_a()));
assert(is_within_object(x, x.get_b()));
}
注意a
and b
有不同的访问说明符。
指针比较定义在[expr.rel]/3-4 http://eel.is/c++draft/expr.rel#3:
比较不相等的指针与对象的定义如下:
- 如果两个指针指向同一个数组的不同元素,或者指向其子对象,则指向下标较高的元素的指针比较大。
- 如果两个指针指向同一对象的不同非静态数据成员,或者指向此类成员的子对象,则递归地,指向后来声明的成员的指针比较更大,前提是这两个成员具有相同的访问控制并且它们的类不是联盟。
- 否则,两个指针都不会比另一个指针更大。
如果两个操作数 p 和 q 比较相等,则 p=q 均产生 true,pq 均产生 false。否则,如果指针 p 比较大于指针 q,则 p>=q、p>q、qp 都会产生 false。否则,每个运算符的结果是未指定的。
我们可以从中得出什么结论?
有一个总订单对象内相同类型的指针,但有no order指向不同对象或具有不同访问控制的不同子对象的指针。缺乏一般的指针总顺序使得is_within_object()
意义不大。在您期望它返回的情况下true
, 有用。在您期望它返回的情况下false
,这些运算符的结果是未指定的?这不是一个非常有用的结果。
That说,我们确实有一个巨大的漏洞[比较] http://eel.is/c++draft/comparisons#2:
对于模板less
, greater
, less_equal
, and greater_equal
,任何指针类型的特化都会产生严格的全序,该全序在这些特化之间保持一致,并且也与内置运算符施加的偏序一致<
, >
, <=
, >=
.
因此,以下内容将得到明确定义:
template<class T>
auto byte_address(T& p) {
return reinterpret_cast<std::byte const*>(std::addressof(p));
}
template<class Object, class Part>
bool is_within_object(Object& object, Part& part)
{
auto first = byte_address(object);
auto last = first + sizeof(Object);
auto p = byte_address(part);
return std::less_equal<std::byte*>{}(first, p) &&
std::less<std::byte*>{}(p, last);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)