Find elements of std::set by custom comparison with value of different type

前端 未结 1 1598
梦谈多话
梦谈多话 2020-12-20 16:25

Consider the following toy example of an std::set with a custom comparator:

#include 

struct A {
  A() : a(cnt++) {}
  const int a;
         


        
相关标签:
1条回答
  • 2020-12-20 16:47

    With C++14 you can utilize "transparent" comparator:

    #include <iostream>
    #include <set>
    #include <type_traits>
    
    class A
    {
        public: explicit A() : a{cnt++} {}
        private: explicit A(int) = delete;
        public: const int a;
        private: static int cnt;
    };
    
    int A::cnt{};
    
    class Comparator
    {
        // this member is required to let container be aware that 
        // comparator is capable of dealing with types other than key
        public: using is_transparent = std::true_type;
    
        public: bool operator()(const int & left, const A& right) const
        {
            return left < right.a;
        }
    
        public: bool operator()(const A & left, const int& right) const
        {
            return left.a < right;
        }
    
        public: bool operator()(const A& left, const A& right) const
        {
            return left.a < right.a;
        }
    };
    
    int main()
    {
        std::set<A, Comparator> sa{};
        for (int i{}; i < 10; ++i)
        {
            sa.emplace();
        }
        std::cout << sa.find(3)->a << std::endl;
        return 0;
    }
    

    online compiler

    Before C++14 heterogenous lookup was available in ::boost::intrusive::set:

    #include <boost/intrusive/set.hpp>
    #include <iostream>
    
    namespace bi = ::boost::intrusive;
    
    // hook contains set node data, supports various options, can be a member
    class A: public bi::set_base_hook
    <
        bi::link_mode<bi::link_mode_type::safe_link>
    >
    {
        public: explicit A() : a{cnt++} {}
        private: explicit A(int) = delete;
        public: const int a;
        private: static int cnt;
    };
    
    int A::cnt{};
    
    class Comparator
    {
        public: bool operator()(const int & left, const A& right) const
        {
            return left < right.a;
        }
    
        public: bool operator()(const A & left, const int& right) const
        {
            return left.a < right;
        }
    
        public: bool operator()(const A& left, const A& right) const
        {
            return left.a < right.a;
        }
    };
    
    int main()
    {
        bi::set<A, bi::compare<Comparator>> sa{Comparator{}};
        for (int i{0}; i < 10; ++i)
        {
            sa.insert(*new A{}); // typically user manages object creation
        }
        // comparators may vary
        std::cout << sa.find(3, Comparator{})->a << std::endl;
        return 0;
    }
    

    online compiler

    0 讨论(0)
提交回复
热议问题