2009-11-13 72 views
1

我目前正在開發一個syntaxic分析器類,它需要在代碼的某個位置對結構進行排序,以保存關於運算符的信息。每個操作員都有一個優先級,這是用戶定義的,通過我的分析器類的公共成員函數。因此,在排序時,我需要我的排序功能根據相應運算符的優先級排序元素。我使用下面的代碼比較元素:在比較函數中使用非靜態類成員

bool parser::op_comp(const op_info& o1, const op_info& o2) { 
    op_def& op1 = operators[o1.op_char]; 
    op_def& op2 = operators[o2.op_char]; 

    return op1.priority > op2.priority; 
} 

注意,我不得不做出這個功能靜態的,因爲它是一個類的內部定義。

實際上,我的比較函數比較了op_char類型的元素,並且我從包含op_def類型元素(其中具有「優先級」字段的元素)的映射中檢索運算符def。

我面臨的問題是,我不能管理使用std::sort(ops.begin(), ops.end(), std::mem_fun_ref(&parser::op_comp))(其中OPS是vector of op_info)方法我碰到下面的錯誤,這聽起來很符合邏輯:

錯誤:使用無效成員`解析器::運營商'在靜態成員函數

這裏是我的問題:我怎麼能強制std :: sort使用從非靜態成員類的元素的使用comp函數?很顯然,函數應該是非靜電,但我不能設法使用它,如果我不使它靜態...

在此先感謝您的幫助, CFP。

回答

3

使用函子,而不是一個函數:

struct op_comp : std::binary_function<op_info, op_info, bool> 
    { 
    op_comp(parser * p) : _parser(p) {} 
    bool operator() (const op_info& o1, const op_info& o2) { 
     return _parser->op_comp(o1, o2); 
    } 
    parser * _parser; 
}; 

這樣的方法op_comp可以保持非靜態。然而,調用者需要解析器的一個實例,所有操作符都存儲在哪裏。這是我們的新仿函數的用法:

std::sort(ops.begin(), ops.end(), op_comp(&my_parser)); 

哪裏my_parser是您正在使用的解析器的實例。另外,如果你是從解析器調用std::sort,可以簡單的寫:

std::sort(ops.begin(), ops.end(), op_comp(this)); 
+0

太棒了!這確實很有效。 – 2009-11-14 18:42:25

5

使運算符也是靜態的,並且您可以在op_comp中使用它。

或者,使用仿函數而不是函數:

class myCompareClass { 
    public: 
    bool operator() (
    const op_info& o1, const op_info& o2) { 
    op_def& op1 = operators[o1.op_char]; 
    op_def& op2 = operators[o2.op_char]; 

    return op1.priority > op2.priority; 
    } 
    private: 
    ... operators ... 
} myCompareObject; 

std::sort(ops.begin(), ops.end(), myCompareObject) 

查看更多的例子在cplusplus.com

+1

謝謝您!然而,我的問題是'運營商'的內容取決於我正在處理的「解析器」的哪個實例。 我意識到,另一種解決方案也是在創建這樣的對象時,簡單地將「優先級」信息複製到每個op_info對象。 在這個網站上,快速和好的答案以及人們的表現有多好讓我印象深刻。謝謝! – 2009-11-14 18:46:39

+0

這是一個非常好的解決方案!謝謝 – 2015-03-20 11:15:05

3

如果你想op_comp是非靜態的,你可以使用Boost.Lambda或Boost.Bind:

parser my_parser; 
sort(ops.begin(), ops.end(), bind(&parser::op_comp, ref(my_parser))); 
+0

+1。如果可用,使用TR1'std :: tr1 :: bind';否則'boost :: bind'。 – 2009-11-13 20:17:46

相關問題