C ++ std :: set uniqueness override

时间:2017-01-04 16:50:50

标签: c++ stl c++14

std::set<T>容器如何检查两个对象是否唯一?我尝试重写等于运算符(==),但它没有用。

我想这样做的原因是我让我们说一个人类,我指定我的人是同一个人,如果他们有相同的名字(甚至可能是生日,地址等)。

ccpreference.com中,他们写下以下内容(我有点不清楚):

  

标准库的每个地方都使用比较概念,唯一性   通过使用等价关系来确定。不精确的说,   两个对象a和b被认为是等价的(不唯一),如果两者都不相同   比较少:!comp(a,b)&amp;&amp; !comp(b,a)。

我认为,这个问题也扩展到其他STL容器甚至算法(甚至可能扩展到整个STL)。因此,如果将来我想使用函数std::find,我会查找人的名字而不是对象本身。这是对的吗?

修改

我想添加一些示例代码。

// My operator overloading comparing two strings.
bool operator==(Node & rhs) const {
        return this->name.compare(rhs.name);
}

然后,在UnitTest中,我将两个具有相同名称的对象添加到集合中。它被添加两次(但根据operator==应该是相同的。

void test_adding_two_identical_nodes() {
    // The pool is a set<Node> inside
    model::Node_Pool pool{};
    pool.store_node(model::Node{"Peter"});
    pool.store_node(model::Node{"Peter"});
    // Should be only 1 because the same node should be added once into a set.
    ASSERT_EQUAL(1, pool.size());
}

2 个答案:

答案 0 :(得分:3)

import UIKit class Order { var stations = [Station]() var companies = [String]() } class Station { let name: String let amount: Int init(name: String, amount: Int) { self.name = name self.amount = amount } } class TableViewController: UITableViewController { var orders = [Order]() override func viewDidLoad() { super.viewDidLoad() tableView!.rowHeight = UITableViewAutomaticDimension tableView!.estimatedRowHeight = 44.0 //simulated data let order1 = Order() order1.companies.append("Global @ CITGO Braintree, Braintree") order1.companies.append("Exxon @ Global, Chelsea") order1.stations.append(Station(name: "Tyngsboro Mobil #2871", amount: 4000)) order1.stations.append(Station(name: "Grafton St #10095", amount: 15000)) orders.append(order1) let order2 = Order() order2.companies.append("Exxon @ Global, Chelsea") order2.stations.append(Station(name: "Winstead Citgo #2001", amount: 3000)) orders.append(order2) let order3 = Order() order3.companies.append("MSCG @ Sunoco Partners") order3.stations.append(Station(name: "Citgo #123", amount: 7000)) order3.stations.append(Station(name: "Mobil #345", amount: 12500)) order3.stations.append(Station(name: "Exxon #567", amount: 300)) order3.stations.append(Station(name: "Citgo #789", amount: 6100)) order3.stations.append(Station(name: "Stoughton Mobil #2744", amount: 9098)) order3.stations.append(Station(name: "Westborough Mobil #2720", amount: 120000)) orders.append(order3) } override func numberOfSections(in tableView: UITableView) -> Int { return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return orders.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as! TableViewCell let order = orders[indexPath.row] cell.companyLabel.text = "" for (index, company) in order.companies.enumerated() { cell.companyLabel.text! += company if index < order.companies.count - 1 { cell.companyLabel.text! += "\n" } } for station in order.stations { // create horizontal stack view to arrange the station name and amount let horizontalStackView = UIStackView() horizontalStackView.axis = .horizontal let nameLabel = UILabel() nameLabel.translatesAutoresizingMaskIntoConstraints = false nameLabel.text = station.name horizontalStackView.addArrangedSubview(nameLabel) let amountLabel = UILabel() amountLabel.translatesAutoresizingMaskIntoConstraints = false amountLabel.addConstraint(NSLayoutConstraint(item: amountLabel, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: 60)) amountLabel.backgroundColor = UIColor.purple amountLabel.textAlignment = .right amountLabel.textColor = UIColor.white amountLabel.text = String(station.amount) horizontalStackView.addArrangedSubview(amountLabel) // add the horizontal stack view to the vertical stack view containing all stations cell.stackView.addArrangedSubview(horizontalStackView) } return cell } 无法使用std::set<T>进行比较。默认情况下,它使用==进行比较。反过来,std::less<T>默认使用运算符std::less<T>

实现集合的一种方法是覆盖<,如下所示:

operator<

或者,可以在声明#include <set> #include <cassert> struct Person { const char *name; int uid; }; bool operator<(const Person& a, const Person& b) { return a.uid < b.uid; } int main () { Person joe = {"joseph", 1}; Person bob = {"robert", 2}; Person rob = {"robert", 3}; Person sue = {"susan", 4}; std::set<Person> people; people.insert(joe); people.insert(bob); people.insert(rob); assert(people.count(joe) == 1); assert(people.count(bob) == 1); assert(people.count(rob) == 1); assert(people.count(sue) == 0); Person anonymous_3 = {"", 3}; assert( std::strcmp(people.find(anonymous_3)->name, "robert") == 0); } 时将比较运算符作为模板参数传递。在上面的示例中,这可能是比较运算符:

set

struct Person_Compare { bool operator()(const Person& a, const Person& b) const { return a.uid < b.uid; } }; 声明可能如下所示:

std::set

示例的其余部分未更改。

答案 1 :(得分:0)

首先,不要覆盖比较运算符来比较除TOTAL等价之外的任何东西。否则你最终会遇到维护噩梦。

那就是说,你要覆盖operator <。您应该改为设置比较器类型。

struct compare_people : std::binary_function<person,person,bool>
{
    bool operator () ( person const& a, person const& b) const { return a.name() < b.name();
};

std::set<person, compare_people> my_set;