2个问题:
> < li>
以下代码是否符合定义的行为?
是否有任何可能的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
和 b
具有不同的访问说明符。
指针比较在[expr.rel]/3-4中定义:
比较指向对象的不等指针定义如下:
如果两个操作数p和q比较相等,则p
我们可以从中得出什么结论?
一个对象中有相同类型的指针的总顺序,但是没有指向不同对象或具有不同权限改造的不同子对象的指针的顺序。这种缺乏一般的指针总顺序使得is_within_object()
没有什么意义。在您期望它返回true
的情况下,它是有效的。在您期望它返回false
的情况下,这些运算符的结果是未指定的?这不是一个非常有用的结果。
也就是说,在[比较]的形式上,我们确实有一个巨大的漏洞:
对于模板less
,more
,less_等于
和greater_等于
,任何指针类型的特化都会产生严格的总顺序,该顺序在这些特化之间是一致的,并且也与内置运算符施加的部分顺序一致
因此,以下内容将被很好地定义:
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);
}