将自定义比较器用于带有自定义构造函数的std :: set

时间:2019-03-25 01:07:31

标签: c++ stl

假设我有课

class Custom
{
public:
    Custom (int x, int y) : x (x), y (x) {} 
    bool operator() (int a, int b)
    {
        return a < x && y < b;
    }
private:
    int x, y;
};

我想要的是

std::set<int, Custom> s 

使用Custom的自定义构造函数(即Custom(1、2))

我该如何实现?

此外,如果我想在unordered_map中使用它,例如

std::unordered_map<string, std::set<int, Custom>> ht

我该怎么做?

2 个答案:

答案 0 :(得分:1)

制作场景

构造集合时,需要提供比较器:

using std::unordered_map;
using std::set; 
using std::string; 

set<int, Custom> s(Custom(10, 20)); 
// Or: 
auto s = set<int, Custom>(Custom(10, 20)); 

这是因为在开始将元素分配给集合时,它需要有一个比较器,并且由于比较器具有参数,因此需要知道它们是什么。

在地图中使用场景

比较器必须是默认可构造的,因为调用map["key"]将默认构造该元素(如果不存在):

class Custom
{
   public:
    // Add a default constructor
    Custom() : x(0), y(0) {}
    Custom (int x, int y) : x (x), y (x) {} 
    bool operator() (int a, int b)
    {
        return a < x && y < b;
    }
   private:
    int x, y;
};

在这种情况下,可以为比较器提供默认的构造函数,因为我们可以重新分配它:

unordered_map<string, set<int, Custom>> map; 
map["some key"] = set<int, Custom>(Custom(10, 20)); 

如果我没有默认的构造函数怎么办?

我们仍然可以使用unordered_map,但是我们必须使用map.at("key")map.emplace("key", value)而不是map["key"]

unordered_map<string, set<int, Custom>> map; 
set<int, Custom> s(Custom(10, 20)); 
set<int, Custom> s2(Cunstom(30, 40)); 
s2.insert(1);
s2.insert(2); 
s2.insert(3); // put some stuff in the set

map.emplace("Hello", s); //Inserts the set

map.insert({"Hello", s2}); //Inserts the set as a key-value pair

我们可以使用map.at获取值:

// This line gets the set at "Hello", and inserts 10 into the set:
map.at("Hello").insert(10); 
// If "Hello" isn't in the map, there's an error

我们可以使用map.find("key")检查地图中是否有东西:

// Get an iterator to the key value pair held by "Hello" in the map:
// An iterator acts like a pointer
auto iterator = map.find("Hello"); 

if(iterator == map.end()) // Check if we found the thing
{
    std::cout << "Couldn't find 'Hello' in the map"; 
} 
else 
{
    // Get the key from the iterator
    string key = iterator->first; 
    // Get a reference to the value from the iterator
    set<int, Custom>& value = iterator->second; 

}

答案 1 :(得分:0)

std::set有一个重载的构造函数,该构造函数将比较器类的实例作为参数。如果比较器类没有默认的构造函数(如此处所示),则必须使用该构造函数构造std::set的每个实例:

std::set<int, Custom> set_instance{ Custom{4,4} };

std::set实例使用Custom{4,4}作为其比较器。此集合的不同实例可以使用不同的比较器。

由于此std::set没有默认的构造函数,因此您无法使用地图的[]运算符,因此您需要做一些工作。 []将尝试默认构造值类的实例,并且此集合不再具有可用的默认构造函数;因此您将需要使用find()insert()来明确搜索和/或在地图中插入新值。 C ++ 17添加了一个insert_or_assign()方法,使此操作变得更加简单。