2012-02-08 38 views
4

in another message of mine所述,不可能將2個指針與「<」(小於)的成員函數進行比較。或者至少,這會導致未定義的行爲。std :: set中的函數和方法指針

我剛纔設法編譯此代碼都與Visual C++以及GCC:

template <class Receiver, class Param = void*, class Return = void> 
class EventReceiver : public IFunction<> { 

protected: 

    std::set< Return(Receiver::*)(Param) > test; 
    std::set< Return(*)(Param) > test2; 
... 

據我所知,做一個std ::地圖或std ::設置的任何東西,它必須能夠將該組的值與「<」進行比較。這是否意味着上述容器或實際的編譯器有一個以這種方式比較指針與方法的工作實現?

+0

我的回答是不正確的 - 指向成員和指針是不一樣的。我很抱歉! – templatetypedef 2012-02-08 19:42:36

+0

@templatetypedef FWIW C++ 11中的相應措辭在§20.8.5/8之下。這令人迷惑。我邀請了一些(編譯器構建)的朋友在這裏發表意見 – sehe 2012-02-08 19:48:52

+0

@Xeo給出了一個想法[聊天](http://chat.stackoverflow.com/transcript/message/2582471#2582471) – sehe 2012-02-08 20:12:37

回答

0

那麼,這是在現實誤導,該示例代碼編譯。事實是,套是無法使用。每次嘗試向其中插入數據都會產生預期的錯誤。

這就是C++模板函數的「黑暗面」。在你使用它們之前它們是不存在的(因此在你做之前不會產生編譯錯誤)。

檢查了這一點:

#include <set> 

class X {}; 

int main() { 

    typedef void(X::*FuncPtr)(); 
    std::set<FuncPtr> set; 
    std::less<FuncPtr> less; 
    FuncPtr f1; 
    FuncPtr f2; 
    //set.insert(f1); // both of these lines 
    //less(f1,f2);  // produce an error 
}; 

刪除任何最後兩行的意見產生錯誤:

類型「無效(X :: * const的)的無效操作數() '和 '空隙(X :: * 常數)()' 爲二進制 '運算符<'

Compile it online yourself here

0

std::set<T>使用std::less<T>,而不是直接使用小於運算符。當T是一個指針類型時,std::less<T>保證是一個總的順序,即使小於運算符不是。

編輯:C++ 98標準的第20.3.3節說「指針類型」,它(我認爲)包括指向函數的指針,但不包含指向成員的指針。

+1

不感興趣「即使內置運營商<, >,<=, > =沒有,任何指針類型的專業化都會產生全部訂單。」 - 現在的問題是,「指向成員」類型也是「指針」類型?該標準似乎說不,看到另一個問題。 – Xeo 2012-02-08 20:06:55

+0

你說得對。我已經修改了我的答案。 – 2012-02-08 20:27:42

+1

那麼,std :: less也不起作用! [std :: less ()。operator()(function,other-> function))]不會編譯:error C2296:'<':非法,左操作數有類型'void(__thiscall Fair :: PtrIcon :: * const)(Fair :: Pointer *)'!!! – 2012-02-08 20:27:45