4

Let us say that p below has to be a pointer to const X. Then it is not possible to call find for a set of pointers to X with my special compare class. Is that a shortcoming of 'set' and 'find'? Is it safe to solve it with const_cast as I have done?

struct X{
    std::string key;
    X(std::string s): key(s) {}
};
struct compare {
    bool operator() (const X* lhs, const X* rhs) const {
        return lhs->key < rhs->key;
    }
};
int main() {
    std::set<X*,compare> m;
    const X a("hello");
    const X*p=&a;
    std::set<X*,compare>::const_iterator it=m.find(const_cast<X*>(p));
}
user2304458
  • 363
  • 1
  • 2
  • 11

1 Answers1

4

This use of const_cast is safe, but any usage of const_cast is scary. const_cast is legal so long as you don't modify the object through the cast, which std::set::find does not do.

However, you don't need a const_cast here. If you make your comparator transparent, that opts into allowing find to search based on anything comparable to the key type. This is exactly what we want:

struct compare {
    using is_transparent = void; // doesn't matter which type you use

    bool operator() (const X* lhs, const X* rhs) const {
        // You might want to consider using std::less<X*> to compare these.
        // std::less<T*> can compare pointers which are not part of the
        // same array, which is not allowed with just a simple less-than
        // comparison.
        return lhs->key < rhs->key;
    }
};

Complete example: https://godbolt.org/z/NsZccs

Justin
  • 24,288
  • 12
  • 92
  • 142