2013-03-12 58 views
0

當我嘗試使用這樣的代碼:錯誤與運營商<超載,非法操作數

namespace 
{ 
    typedef boost::shared_ptr<float> sharedFloat; 
} 

static bool operator<(const sharedFloat& inOne, float inTwo) 
{ 
    return *inOne < inTwo; 
} 

static void foo() 
{ 
    std::vector<sharedFloat> theVec; 
    std::vector<sharedFloat>::iterator i = 
     std::lower_bound(theVec.begin(), theVec.end(), 3.4f); 
} 

我得到一個錯誤:

error: invalid operands to binary expression ('boost::shared_ptr<float>' and 'float') 

(的指針在執行<比較)所以,當我提供operator<這些操作數時,爲什麼它們是無效的?

如果我改用比較函子,

namespace 
{ 
    typedef boost::shared_ptr<float> sharedFloat; 

    struct Comp 
    { 
     bool operator()(const sharedFloat& inOne, float inTwo) 
     { 
      return *inOne < inTwo; 
     } 
    }; 
} 

static void foo() 
{ 
    std::vector<sharedFloat> theVec; 
    std::vector<sharedFloat>::iterator i = 
     std::lower_bound(theVec.begin(), theVec.end(), 3.4f, Comp()); 
} 

然後再編譯。我可以這樣做,但我想知道爲什麼第一次嘗試失敗。

解決方案後添加:Namespaces & Interface Principle通過Herb Sutter幫助澄清這些東西更多。

+1

如果將typedef從命名空間中取出,它是否工作? – EHuhtala 2013-03-12 21:23:35

+0

@EHuhtala,不,這沒有效果。 – JWWalker 2013-03-12 21:33:24

回答

3

operator <的調用是在std名稱空間內執行的。因此,編譯器將在std名稱空間和其參數的名稱空間(ADL)中尋找合適的operator <過載。如果找到一個運營商(即使它不可行!),也會搜索到(!),封裝命名空間爲而非已搜索。

由於您的operator <在全局命名空間中定義,編譯器將不考慮(因爲另一個重載operator <std命名空間存在,並且名稱前被發現查找可能會考慮封閉命名空間)。

最後,由於std::operator <不可行,因此編譯器將發出錯誤。

當傳遞你自己的函子作爲最後一個參數時,情況明顯不同:不是尋找一個可行的operator <,而是調用了參數本身,並且所有的編譯都很好。

+0

爲什麼'浮點'參數不在全局名稱空間中? – JWWalker 2013-03-12 23:42:22

+0

@JWWalker:'float'是一種內置的語言類型,它沒有在任何名字空間中定義。爲了讓人信服,試着做':: float x = 0;',你會看到編譯器給你一個錯誤。 – 2013-03-12 23:45:29

4

您的operator<將不會被lower_bound找到,因爲它不在與您使用的類型相關的任何名稱空間中。

編譯器將在名稱空間stdboost中查找,但不在全局名稱空間中,因爲沒有涉及任何相關內容。

當你通過Comp explicilty它的作品,因爲然後編譯器不必搜索匹配的運算符。