在以下代码中,令人惊讶的是,当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) {
        ^


最后几行显示了歧义,其中编译器显示了两个候选。

为什么存在这种歧义?我该怎么压抑它?

最佳答案

看起来有些gcc版本具有此特殊功能,可以将这些消息立即打印出来。例如,所有构建都基于coliru do this

这些消息不是错误,因为生成了目标文件,它们也不是警告,因为-Werror不会将它们变成错误。它们看起来像是编译器错误。显然,不能用编译器标志来抑制这些非警告。

我的计算机上gcc的相同确切版本不会使用此代码显示任何消息。它们确实使用similar code打印常规警告(带有彩色的“警告”,不可抑制但容易出错的警告)。

在coliru上,制作第二个operator() const suppresses the messages

09-25 20:42