2011-09-27 59 views
0

我有一个类,我已经为其定义了比较运算符。以下是我的代码写STL为相同的用户定义类型设置和映射

#include <set> 
#include <map> 
#include <list> 

    template <typename _TyV> 
    class Element { 
    public: 
     Element(_TyV in) : m_Label(in){} 
     ~Element() {} 
     bool operator < (const Element & right) const { 
      return m_Label < right.m_Label; 
     } 
    private: 
     _TyV m_Label; 
    protected: 
    }; 
    typedef Element<int> ElementType; 

    int main (int argc, char **argv) { 
     std::set<ElementType> mySet; 
     for (int i = 0; i < 10; i++) { 
      mySet.insert(ElementType(i)); 
     } 
     std::map<ElementType*, std::list<ElementType*> > myMapList; 
     return 0; 
    } 

我迷惑于如何我std::map会工作,因为我感兴趣的std::map元素是指向ElementType。我真正想要的是存储在std::set实际数据,并在std::map

主要混淆使用指针,以这些元素是围绕less than operator

回答

7

你的地图,std::map<ElementType*, std::list<ElementType*> >的关键类型作为其比较器使用std::less,为正常。

std::less指针类型被定义为产生一致的排序,但排序是基于地址只有,而不是它可能指向的任何东西。

因此,您的设置根据Element中的operator<对其内容进行排序,但映射会根据键的实际指针值对它们进行排序。这可能不是你想要的:(1)它使不同的Element<int>值包含相同的m_Label值作为映射中的不同键,并且(2)这意味着映射将以与集不同的顺序。但std::map可以带一个额外的模板参数来提供一个比较器,所以你可以改变它。

你可以编写一个比较器,它需要两个指针,并比较它们指向的对象。当然,假设一旦你使用指针作为地图中的一个键,你确定它指向的对象将被粘住(在set,我假设,但是如果没有,那么在这里插入样板讲座shared_ptr)。由于Element<int>是便宜的复制,所以使用ElementType作为密钥而不是ElementType*几乎肯定会更好。但是如果int仅仅代表您将来使用的复制代价很高的内容,那么请更改map比较器。

您可能不在意map中元素的顺序。如果你不这样做,并且如果在map中查找的唯一东西是指向set中的对象的指针,那么使用ElementType*作为映射关键字而不指定比较器应该没问题。

+0

ElmentType在这个例子中很便宜,但我希望我的库能够处理重和大的对象,并试图找出避免不必要的副本的选项。根据你的解释,你认为我也可以有迭代器的std :: map。即关键的地图将在迭代器std :: set – Avinash

+1

@Avinash:不,''set :: iterator'不是一个随机访问迭代器,所以它没有'operator <'(或者一个'std :: less'专业化)。 –

+0

即使使用自定义比较器,这也行不通? – Avinash