2014-08-28 110 views
0

我正在從一種編程風格移動到另一種編程風格的代碼庫。C++技巧來避免指針比較

我們定義了一個名爲Operand類型,如:

class Operand 
{...}; 

然後我們有

class OperandFactory 
{ 
    public: 
    const Operand *make_operand (...); 
}; 

用於散列Operand,並保持在一個表OperandFactory。因此,如果您使用相同的參數調用make_operand,則您將獲得與Operand相同的指針和指針比較。現在我需要添加一個功能,這將使這不可行。所以,我在Operand中實現了operator==,並且如果我在Operand上做了指針比較,我希望以某種方式在編譯時(更好)或運行時(好於沒有)錯誤生成。達到此目的的最佳方式是什麼?

這只是在這個過渡階段使用,所以我不介意解決方案看起來像一個黑客,只要它捕獲代碼庫中的所有比較。

+1

顯示代碼或至少是您實際嘗試實現的最小工作簡化示例。 – Alex 2014-08-28 13:03:44

回答

3

您可以重載操作符的地址以返回句柄並聲明兩個句柄(沒有定義)的比較。這會導致鏈接器錯誤。

#include <iostream> 

class Op; 

class Handle { 
    Op *pri_; 
public: 
    explicit Handle(Op *o) : pri_(o) {} 
    Op *operator->() const { return pri_; } 
    Op &operator*() const { return *pri_; } 
}; 

// force compile time errors on comparison operators 
bool operator==(const Handle &, const Handle &) = delete; 
bool operator!=(const Handle &, const Handle &) = delete; 
bool operator>=(const Handle &, const Handle &) = delete; 
bool operator<=(const Handle &, const Handle &) = delete; 
bool operator<(const Handle &, const Handle &) = delete; 
bool operator>(const Handle &, const Handle &) = delete; 

class Op { 
    int foo_; 
public: 
    explicit Op(int i) : foo_(i) { } 
    Handle operator&() { return Handle(this); }; 
    void touch() const { std::cout << "foobar"; } 
}; 


int main(int argc, char **argv) { 
    Op i{10}; 
    Op j{20}; 

    auto c = &j; // works 
    c->touch(); // works 
    (*c).touch(); // works 

    if (&j == &i) { 
     /* will not compile */ 
    } 

} 

注意

你必須履行Handlerandom_access_iterator要求!

Op i{10} 
Handle ref = &i; 

ref++; ref--; ++ref; --ref; ref = ref + 10; ref = ref - 10; // should all work. 
+1

您可以使用'= delete'(自C++ 11以來)具有編譯器錯誤而不是鏈接器錯誤。 – Jarod42 2014-08-28 13:39:46

2

在您的Operand類中添加運算符將無濟於事:要檢測指針Operand s的比較結果。不幸的是,本地類型操作符不能被重載,指針是本機類型的。這不是你正在尋找的解決方案。

+4

您可以重載操作符的地址以返回句柄並聲明兩個句柄(沒有定義)的比較。這會導致鏈接器錯誤。 – Alex 2014-08-28 13:06:31

+0

開箱即用思考。你說對了。 – Quentin 2014-08-28 13:09:26