Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
224 views
in Technique[技术] by (71.8m points)

c++ - Is using std::tuple to implement operator<, = etc. efficient and correct?

I find that I am recently often using std::tuple to implement ordering, equality operators, like in below example. Is this a correct and efficient approach? Its especially usefull when multiple variables should be compared in such operators.

#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <functional>
#include <tuple>

struct CustomerHash;
class Customer {
    std::string name;
    int age;
public:
    Customer(const std::string& name, int age) : name(name), age(age) {
    }
    
    bool operator<(const Customer& rop) const {
        return std::tuple<std::string, int>(name, age) < std::tuple<std::string, int>(rop.name, rop.age);
    }
    bool operator==(const Customer& rop) const {
        return std::tuple<std::string, int>(name, age) == std::tuple<std::string, int>(rop.name, rop.age);
    }
    
    friend struct CustomerHash;
};

struct CustomerHash {
    std::size_t operator()(const Customer& c) const {
        return std::hash<std::string>()(c.name) ^ c.age;
    }
};

int main(int argc, const char * argv[]) {
    std::unordered_set<Customer, CustomerHash> cmap;
    cmap.insert({"Mike", 40});
    cmap.insert({"Andy", 42});
    cmap.insert({"Jon", 40});
    std::cout << cmap.contains({"Andy", 42});
    return 0;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It's correct, but it's not efficient, because the constructor of std::tuple will copy all the values. This also means you can't use it to compare non-copyable types.

Instead you could use std::tie, which needs a bit less code and doesn't copy the values, but creates a tuple of references.

Your operator< would then become:

bool operator<(const Customer& rop) const {
        return std::tie(name, age) < std::tie(rop.name, rop.age);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...