2016-12-29 51 views
0

在下面的代碼,g ++編譯器出奇不能決定當它們被嵌入在一個結構,作爲在一組比較器的參數使用哪個操作者:如何解決運算符重載嵌入結構中的歧義?

#include <string> 
#include <set> 

struct KeyWord { 
    std::string str; 
    int qt; 
    KeyWord(const std::string aKw = "", const int aQt = 0) : str(aKw), qt(aQt) {} 
}; 

struct CompareKeywords { 
    bool operator() (const std::string& left, const std::string& right) const { 
    if (left.size() > right.size()) return true; 
    else if (left.size() < right.size()) return false; 
    else return (left < right); 
    } 
    bool operator() (const KeyWord& left, const KeyWord& right) { 
    if (left.str.size() > right.str.size()) return true; 
    else if (left.str.size() < right.str.size()) return false; 
    else return (left.str < right.str); 
    } 
}; 

int main() { 
    std::set<std::string, CompareKeywords> a; 
    std::set<KeyWord, CompareKeywords> b; 
    std::string s("_s_"); 
    KeyWord k("_k_", 1); 
    a.insert(s); 
    b.insert(k); 
} 

這裏是編譯器的輸出:

g++ oa.cpp 
/usr/include/c++/4.9/bits/stl_tree.h: In instantiation of ‘std::pair<std::_Rb_tree_node_base*, std::_Rb_tree_node_base*> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_get_insert_unique_pos(const key_type&) [with _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::key_type = std::basic_string<char>]’: 
/usr/include/c++/4.9/bits/stl_tree.h:1498:47: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >]’ 
/usr/include/c++/4.9/bits/stl_set.h:502:29: required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const value_type&) [with _Key = std::basic_string<char>; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<std::basic_string<char> >; std::set<_Key, _Compare, _Alloc>::value_type = std::basic_string<char>]’ 
oa.cpp:28:13: required from here 
oa.cpp:11:8: note: candidate 1: bool CompareKeywords::operator()(const string&, const string&) const 
    bool operator() (const std::string& left, const std::string& right) const { 
     ^
oa.cpp:16:8: note: candidate 2: bool CompareKeywords::operator()(const KeyWord&, const KeyWord&) 
    bool operator() (const KeyWord& left, const KeyWord& right) { 
     ^
oa.cpp:11:8: note: candidate 1: bool CompareKeywords::operator()(const string&, const string&) const 
    bool operator() (const std::string& left, const std::string& right) const { 
     ^
oa.cpp:16:8: note: candidate 2: bool CompareKeywords::operator()(const KeyWord&, const KeyWord&) 
    bool operator() (const KeyWord& left, const KeyWord& right) { 
     ^
/usr/include/c++/4.9/bits/stl_tree.h: In instantiation of ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, const _Val&) [with _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::basic_string<char> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr = std::_Rb_tree_node_base*]’: 
/usr/include/c++/4.9/bits/stl_tree.h:1502:38: required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = std::basic_string<char>; _Val = std::basic_string<char>; _KeyOfValue = std::_Identity<std::basic_string<char> >; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >]’ 
/usr/include/c++/4.9/bits/stl_set.h:502:29: required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const value_type&) [with _Key = std::basic_string<char>; _Compare = CompareKeywords; _Alloc = std::allocator<std::basic_string<char> >; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<std::basic_string<char> >; std::set<_Key, _Compare, _Alloc>::value_type = std::basic_string<char>]’ 
oa.cpp:28:13: required from here 
oa.cpp:11:8: note: candidate 1: bool CompareKeywords::operator()(const string&, const string&) const 
    bool operator() (const std::string& left, const std::string& right) const { 
     ^
oa.cpp:16:8: note: candidate 2: bool CompareKeywords::operator()(const KeyWord&, const KeyWord&) 
    bool operator() (const KeyWord& left, const KeyWord& right) { 
     ^

最後一行顯示編譯器顯示兩個候選項時的不明確性。

爲什麼這種歧義存在?我應該如何抑制它?

+2

我在您發佈的文字中看不到「不明確」或類似的詞。它看起來像你編輯了關鍵部分。但作爲一個猜測,第二個不是「常量」,這可能是令人困惑的事情。 –

+0

@Pete Becker我剛剛測試了它,你完全正確:它看起來像編譯器不能決定添加const到比較對象成員與一個確切的字符串參數匹配vs隱式地創建一個字符串的關鍵字,一個精確的函數常量匹配。 –

+1

在此示例中,製作第二個'operator()''const'消除了這些消息。 –

回答

2

它看起來像gcc的一些版本有這種打印這些消息的獨特功能。例如,所有內容均基於coliru do this

這些消息不是錯誤,因爲生成了目標文件,並且它們不是警告,因爲-Werror不會將它們變成錯誤。它們看起來很像編譯器錯誤。顯然,用編譯器標誌不能抑制這些非警告。

我的機器上的gcc的相同準確版本不會打印任何帶代碼的消息。他們確實定期打印(使用similar code來標記帶有顏色的「警告」,不可抑制,但可轉向錯誤)警告。

關於coliru,製作第二個operator()constsuppresses the messages

0

兩個獨立struct與它們中的每專用於一種類型的只有一個操作者解決了這個問題:

#include <string> 
#include <set> 

struct KeyWord { 
    std::string str; 
    int qt; 
    KeyWord(const std::string aKw = "", const int aQt = 0) : str(aKw), qt(aQt) {} 
}; 

struct CompareStrings { 
    bool operator() (const std::string& left, const std::string& right) const { 
    if (left.size() > right.size()) return true; 
    else if (left.size() < right.size()) return false; 
    else return (left < right); 
    } 
}; 
struct CompareKeywords { 
    bool operator() (const KeyWord& left, const KeyWord& right) { 
    if (left.str.size() > right.str.size()) return true; 
    else if (left.str.size() < right.str.size()) return false; 
    else return (left.str < right.str); 
    } 
}; 

int main() { 
    std::set<std::string, CompareStrings> a; 
    std::set<KeyWord, CompareKeywords> b; 
    std::string s("_s_"); 
    KeyWord k("_k_", 1); 
    a.insert(s); 
    b.insert(k); 
} 
-1

有在初始代碼中的錯誤:

bool operator() (const std::string& left, const std::string& right) const { 
    bool operator() (const KeyWord& left, const KeyWord& right) { 

抑制的const在第一個聲明的結尾或第二個聲明的結尾解決了問題。但是,我仍然不明白爲什麼編譯器會感到困惑。

所以,要麼:

bool operator() (const std::string& left, const std::string& right) { 
    bool operator() (const KeyWord& left, const KeyWord& right) { 

或:

bool operator() (const std::string& left, const std::string& right) const { 
    bool operator() (const KeyWord& left, const KeyWord& right) const { 

作品。

注意:const功能是否被討論here

因爲我想重載,所以這兩個函數預計會有相同的行爲,所以const都是或者沒有。如果我喜歡不同的行爲與const和另一個沒有(如果我會有一些struct成員,我本來想修改)不同的行爲,下面的第二個解決方案與每個運營商定義單獨struct將是解決方案。