c ++编译器无法使用我重载的<运算符进行位集键比较

c++ Compiler can't use my overloaded < operator for bitset key comparison

我知道我总是可以使用 set(comp) 构造函数为我的 set 初始化比较函数。

但我通常更喜欢重载 运算符 < .

所以当我想使用位集作为设置键时,我使用下面的代码。

#include <bitset>
#include <set>
using namespace std;

bool operator<(const std::bitset<128>& x, const std::bitset<128>& y)
{
  return false;//show the brief idea of overloading operator< ,never mind .
};

int main()
{
  set<bitset<128> > s{ bitset<128>() };
  return 0;
}

编译器在下面给出了这些编译错误。

Error   1   error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const std::bitset<128>'   c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef  193 1   test
Error   2   error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const std::bitset<128>' c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef  193 1   test
Error   3   error C2784: 'bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const _Elem *' from 'const std::bitset<128>'   c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef  193 1   test
Error   4   error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const std::bitset<128>'   c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef  193 1   test
Error   5   error C2784: 'bool std::operator <(const std::move_iterator<_RanIt> &,const std::move_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::move_iterator<_RanIt> &' from 'const std::bitset<128>' c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef  193 1   test
Error   6   error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'const std::bitset<128>'    c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef  193 1   test
Error   7   error C2784: 'bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'const std::bitset<128>'  c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef  193 1   test
Error   8   error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'const std::bitset<128>'    c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef  193 1   test
Error   9   error C2676: binary '<' : 'const std::bitset<128>' does not define this operator or a conversion to a type acceptable to the predefined operator    c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef  193 1   test

但是这段代码可以编译。

#include <bitset>
#include <set>
using namespace std;

struct wrapper
{
  std::bitset<128> a;
};

bool operator<(const std::bitset<128>& x, const std::bitset<128>& y)
{
  return false;
};

bool operator<(const wrapper& x, const wrapper& y)
{
  return x.a<y.a;
};

int main()
{
  set<wrapper> s{ wrapper() };
  return 0;
}

我想知道为什么。

运算符必须在相关 class 的命名空间中重载:

namespace std {
   bool operator<(const bitset<128>& x, const bitset<128>& y)
   {
      return false;//show the brief idea of overloading operator< ,never mind .
   };
}

using namespace std;

// The rest of the code in the question.

已通过 gcc 6.1.1 验证

这与 C++ 中名称查找的复杂性有关。

默认情况下,std::set 使用 std::less<Key> 作为比较器,其实现大致如下:

template <class K>
struct less {
    bool operator()(K const& lhs, K const& rhs) const {
        return lhs < rhs;  // (*)
    }
};

标记的行是实际调用<的地方。要找到要调用的 <,我们查看模板定义的范围(不会找到您的 operator<),然后查看参数的关联命名空间(即 std:: ,并且您的 operator< 不在该命名空间中。将其添加到该命名空间实际上也是非法的)。由于这些查找都找不到任何内容,因此代码格式错误。

您的第二个示例修复了查找的参数相关部分:现在 一个 operator< 在参数的关联命名空间中(即 ::), 它会被发现。

请注意,您仍然可以 std::set std::bitset<N>。您只需为 class 模板提供自定义比较器。