2017-12-02 153 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

相關問題