【问题标题】:C++ STL wrong keys typesC++ STL 错误的键类型
【发布时间】:2011-09-29 12:35:39
【问题描述】:

无法理解:g++ 编译器很生气:

lengths.insert(pair<Deux,long>(d,one));

在哪里

struct Deux {long big; long small};
map<Deux, long> lengths;
Deux d;
long one;

所以,g++ 说,我想念operator&lt;。在为struct Deux 重载operator&lt; 后,我看到了新的有趣,但同样的错误:

map <long, Node*>ArrayOfNodes;
map <long, Node*>::iterator it;  
  for (it=ArrayOfNodes[Root]->nodes.begin();it<ArrayOfNodes[Root]->nodes.end();++it)
      cout<<it->first<<endl;

也用到了结构节点:

struct Node {
   long name;
   long guest;
   map <long,Node*>nodes;
/*bool operator<(const Node& node)const{
 if ((*this).name<node.name) return true;
 if ((*this).name>node.name) return false;
  return (*this).guest<(*this).guest;
}*/

错误是:

    no match for operator< in it < ((Path*)this)->Path::ArrayOfNodes.
 std::map<_Key, _Tp, _Compare, _Alloc>::operator[] [with _Key = long int, _Tp = Node*,
 _Compare = std::less<long int>, _Alloc = std::allocator<std::pair<const long int, Node*> >]
 (((const long int&)((const long int*)(&((Path*)this)->Path::Root))))->Node::nodes.std::map<_Key, _Tp, _Compare, _Alloc>::end 
 [with _Key = long int, _Tp = Node*, _Compare = std::less<long int>, _Alloc = std::allocator<std::pair<const long int, Node*> >]()

【问题讨论】:

  • 什么是编译器错误信息?
  • 为什么不更新您的问题,向我们展示实际代码和实际编译器错误消息?
  • 抱歉,我的网络连接中断了。好的,谢谢,这个重载运算符的问题
  • @loldop:我们投入时间来猜测您的问题。您至少可以更新您的帖子,以便其他人可以从中学习。否则,stackoverflow 可能不适合您,而您更喜欢付费支持。

标签: c++ stl types map key


【解决方案1】:

你没有提到错误信息。总是发布它!

所以,我需要将我的帖子分成两个不同的部分。

缺少声明。

`error: 'Deux' was not declared in this scope`

这是因为 Deux 在您声明 map&lt;&gt; 时是未知的。

您需要在map&lt;Deux, long&gt; 之前声明Deux 之前,因为map&lt;Deux, long&gt; 需要对其参数的完整定义。

缺少比较器。

`error: no match for 'operator<' in '__x < __y'` 

那是因为你还没有为Deux 定义operator&lt;。`

如果您可以定义一个逻辑operator&lt;,即不是为了排序目的而任意选择的,您可以这样做:

// must be in same namespace as Deux
bool operator< (Deux const &lhs, Deux const &rhs) {
    return lhs.foo < rhs.foo;
}

如果需要访问非公共成员,可以将其设为成员函数:

bool operator< (Deux const &rhs) {
    return this->foo < rhs.foo;
}

如果这种比较是任意的,请按照康斯坦丁的建议进行。


下次

您可以通过发布您的实际代码或最小的测试用例以及提及错误消息来节省我们的时间。

【讨论】:

    【解决方案2】:

    您需要在创建地图时声明

    struct Deux     
    {
      long big; 
      long small
    
      bool operator < (const Deux &n) const
      {         
        if(big != n.big)
           return big < n.big;
        else
           return small < n.small;
       }
    };
    

    【讨论】:

      【解决方案3】:

      只是添加另一个回复,这是我将如何实现Deux 以严格排序。我们只使用字典顺序:

      struct Deux
      {
        long big, small;
      
        inline bool operator<(const Deux & o) const
        {
          return big < o.big || (!(o.big < big) && small < o.small);
        }
      };
      
      std::map<Deux, T> m; // works now!
      

      或者,我们可以避免痛苦,然后说:

      typedef std::pair<long, long> Deux;
      std::map<Deux, T> m; // always works, lexicographic compare is provided by default
      

      永远不要重新发明轮子!

      如果您还希望使用 hash_combine 进行配对散列以使用无序容器,请发表评论。

      【讨论】:

        【解决方案4】:

        使用make_pair

        lengths.insert(make_pair<Deux,long>(d,one));
        

        【讨论】:

          【解决方案5】:

          我的猜测是您的结构缺少 compare 函数,以便将您的 Deux 对象作为键进行内部排序。在地图中,它们必须被排序。

          这是std::map的定义

          template < class Key, class T, class Compare = less<Key>,
                     class Allocator = allocator<pair<const Key,T> > > class map;
          

          所以如果你定义一个这样的函数:

          bool compare_deux(Deux& a, Deux& b) {
              return a.big < b.big;
          }
          

          并将其作为模板参数传递:

          map <Deux, long, compare_deux> lengths;
          

          你应该没事的。

          【讨论】:

          • 除了模板参数是函数类型,不是函数指针。 compare_deux 应该是实现bool operator()(Deux const&amp;, Deux const&amp;) 的类。
          • 比较函数也应该适用于const 参数。
          【解决方案6】:

          编译器抱怨Deux 没有operator &lt;(我猜)。键必须是与 operator &lt; 可比较的类,或者您必须将第三个模板参数传递给映射 - 比较器。

          您看,地图以有序的方式保存其键。为了对它们进行排序,它需要一个谓词。默认情况下它会尝试使用operator &lt;

          试着写这样的东西:

          bool operator < (Deux const & d1, Deux const & d2)
          {
             if(d1.big > d2.big)
                return false;
             if(d1.big < d2.big)
               return true;
             return d1.small < d2.small;  
          }
          

          【讨论】:

          • 好的,谢谢,所以我需要这样的东西:bool operator
          • @loldop:我认为我的版本更正确,因为它处理了大小相等的情况
          • +1:但是,我尽量避免重载operator&lt;,除非这样做具有真实、直观的意义(即仅在有意义的情况下说一个T 是“小于“另一个T)。如果我完全满足map 的要求,我通常会定义自己的比较函子,并在创建map 时指定它。但这只是我……
          • @Oli 不,不只是你 :)
          • @Oli:这是一个有效的观点,但我个人更喜欢重载operator &lt;。我不喜欢为 map 明确指定第三个模板参数。但这只是我...... :)
          猜你喜欢
          • 2019-10-11
          • 1970-01-01
          • 1970-01-01
          • 2012-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-30
          • 1970-01-01
          相关资源
          最近更新 更多