3

Say I have a std::set<std::string>, and I wish to know whether it contains the string "name":

#include <string>
#include <set>
using namespace std;
bool has_name(const set<string> &s) {
    return s.find("name") != s.end();
}

The above function constructs and destroys a temporary std::string with value "name". This inefficiency seems unnecessary, because std::string has facilities for comparing against const char* directly. I would like to eliminate this temporary.

I tried using a custom comparator with overloads:

struct str_comp_t {
    bool operator()(const string &s1, const char *s2) const {
        return s1.compare(s2) < 0;
    }

    bool operator()(const string &s1, const string &s2) const {
        return s1.compare(s2) < 0;
    }
};

typedef std::set<string, str_comp_t> string_set_t;
bool has_name_2(const string_set_t &s) {
    return s.find("name") != s.end();
}

However only the variant taking std::string is called; the const char * is ignored.

How can I make this set compare against the constant string directly, instead of constructing an intermediate string?

ridiculous_fish
  • 17,273
  • 1
  • 54
  • 61

1 Answers1

6

In C++14, use transparent comparators:

std::set<std::string, std::less<>> s;
//                    ^^^^^^^^^^^

s.find("Hello");  // no temporary

The transparent comparison predicate std::less<> has a templated operator(), and C++14 containers which are specialized with transparent predicates expose template overloads of find.

Transparent comparators are strictly opt-in, so std::set<std::string> does not automatically get the new overloads.

Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • And unfortunately other than using this technique there's really no way. If your compiler doesn't yet support these you're out of luck unless you want to write your own version, which is completely possible I believe even in C++03. – Edward Strange Oct 26 '14 at 21:32
  • @CrazyEddie: Well, yes, it's a simple library issue. If you don't like the library, you can choose a different one or write your own. Recognizing shortcomings and improving on them is part of the ongoing evolution of the standard library, and when something can be done better, then hopefully it'll eventually improve. – Kerrek SB Oct 26 '14 at 21:36