2017-12-02 41 views
12

2个问题中:是否合法,检查的子对象的地址是否在包含对象的范围

  1. 是有定义的行为也形成了如下的代码?

  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())); 
} 

注意ab具有不同的访问说明。

+4

“需要注意的是A和B具有不同的可见性。”不。他们有不同的**访问说明符**。对于任何明智的可见性概念而言,两者都是“可见的”。将事物私人化并不会使它们消失。 –

+0

我们在讨论什么对象?他们是否符合任何概念,比如'StandardLayout','POD','TriviallyCopyable'?你到达的越具体,你的答案就越精确。否则,答案可能只能围绕您的示例代码进行,这可能不适用于现实世界的问题。 – Jodocus

+1

以下是它变得有趣的地方:'X y; assert(!is_within_object(y,x.get_a()));'这会触发exp.rel 3.3:“否则,两个指针都不会比另一个更大” –

回答

10

指针比较在[expr.rel]/3-4定义:

比较不等对象指针被定义为如下:

  • 如果两个指针指向相同的阵列的不同元件,或者子对象物,指向具有较高下标的元素的指针比较大。
  • 如果两个指针指向同一对象的不同的非静态数据成员,或这些成员的子对象,递归地,指针到后来宣称构件比较大提供的两个成员都具有相同的访问控制和提供它们的类不是一个工会。
  • 否则,既不指针比较大于另一个。

如果两个操作数p和q比较相等,则p= q且p> = q都产生真并且pq都产生假。否则,如果指针p比指针q进行比较时,P> = Q,P> Q,Q < = p和q = p和q> P均产生错误。否则,每个操作员的结果都是未指定的。

,我们可以从中得出什么结论?

有一个对象内的相同类型的指针的总订单,但没有指针指向不同的对象或不同的访问控制的不同子对象的顺序。这种缺乏指针的一般总订单使得is_within_object()意义不大。在你期望它返回true的情况下,它可以工作。在你期望它返回false的情况下,这些操作符的结果是不确定的?这不是一个非常有用的结果。


也就是说说,我们对此有一个巨大的漏洞在[comparisons]形式:

对于模板lessgreaterless_­equalgreater_­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); 
} 
+0

在[比较]中:“当一个 geza

+0

@geza不,它没有。 – Barry

+1

这是否意味着这些模板实际上是以某种方式使用的,即builtins不能?例如,我的意思是,一些算法/容器以这种方式使用它们?它必须是这样定义的一个原因。 – geza

相关问题