如何使用重载的std :: less for std :: map

时间:2012-03-24 05:32:51

标签: c++ stl

我有以下代码段:

typedef char OR[12];

class COR
{
   OR m_or;
public:
   COR(const char* or) { strcpy(m_or, or); }
   COR(const COR& o) { strcpy(m_or, o.m_or); }
   const char* GetOR() const { return m_or; }

#if 0 // I do not wish to use this as it will create a temporary object
   bool operator<(const COR& left, const COR& right) const 
   { return (strcmp(left.m_or, right.m_or) < 0); }
#endif
};

namespace std {
   template<>
   struct less<COR> {
       bool operator()(const COR& cor, const char* or) const 
       { return (strcmp(cor.GetOR(), or) < 0); }
   };
}

当我尝试这个时,我收到一个错误: 错误:没有匹配函数来调用std::map<COR, SomeStruct*, std::less<COR>, std::allocator<std::pair<const COR, SomeStruct*> > >::find(const char*&)

我不想使用任何涉及两个“COR”对象比较的方法。我会将COR与const char *进行比较。你们能建议一种方法吗?

3 个答案:

答案 0 :(得分:9)

几种方法:
注意:这些都不会产生额外的副本,因为值总是通过引用传递(并且因为我们通常不会通过const引用在比较传递中改变对象)。

方法1:

class COR
{
   public:
   // 1: Make it a member function
   //    Thus you only specify the right hand side.
   //    The left is implicit.
   bool operator<(COR const& right) const 
   {
       return (strcmp(m_or, right.m_or) < 0);
   }
};

方法2:

class COR
{
   public:
   // 2: Make it a friend non member function
   //    Note: Just because I declare it here does not make it part of the class.
   //          This is a separate non member function
   //          The compiler makes the destinction because of the `friened`
   friend bool operator<(COR const& left, COR const& right) 
   {
       return (strcmp(left.m_or, right.m_or) < 0);
   }
};

方法3:

class COR
{
    public:
    // Just an example. Just need some way for the functor to access members
    //                  In a way that will allow a strict weak ordering.
    bool test(COR const& right) const {return (strcmp(m_or, right.m_or) < 0);}
};

// Define a functor.
//        This is just a class with the operator() overloaded so that it can 
//        act like a function. You can make it do whatever you like but for
//        comparisons it will be passed two members of the container (accept by const
//        reference and make sure the functor is const member and things will go well).
struct CorTest
{
    bool operator()(COR const& left, COR const& right) const
    {
        return left.test(right);
    }
};

// When you declare the set you just pass as the second template parameter.
//  (or third if it is a map)
std::set<COR, CorTest>        mySet;
std::map<COR, int, CorTest>   myMap;

您使用的方法取决于具体情况 在大多数情况下,我会使用方法(1)。如果我需要一个特殊的排序顺序,我想要使用一个已排序的容器,那么我将使用方法(3)。方法(2)可以用作方法(1)的替代方法,并且在某些情况下更好(但是在我说使用它之前你需要提供有关使用的更多细节)。

答案 1 :(得分:0)

您正在寻找C ++ 14中添加的find(),lower_bound()和upper_bound()的新重载版本。他们正是您要的。

https://en.cppreference.com/w/cpp/container/set/find

答案 2 :(得分:0)

发生此错误是因为您犯了一个错误-std::less operator()的参数类型必须相同。因此,这可行:

template <>
struct std::less<COR>
{
    bool operator()(const COR &a, const COR &b) const { return (strcmp(a.GetOR(), b.GetOR()) < 0); }
};