problems with c++ set container

后端 未结 2 880
长发绾君心
长发绾君心 2020-12-02 02:56

When I try to compile the following code:

    #include 
    #include 
    #include 

    using namespace std;

    t         


        
相关标签:
2条回答
  • 2020-12-02 03:30

    std::set stores its values in a sorted binary tree, so it needs to know how to compare the values it holds. By default it uses std::less as a comparison function, which for un-specialized user defined types tries to call operator<. So, the easiest way to tell the set how to compare your objects is to define an operator< for your class:

    template <class T, class S> 
    class Property
    {
    public:
        pair<T,S> p;
    
        Property(T t, S s) { p = make_pair(t,s);}
    
        bool operator<(const Property<T,S>& rhs) const
        {
            return p < rhs.p;
        }
    };
    

    However, there are also other ways of telling std::set how to compare your type. One is to specialize the std::less template for your class:

    namespace std {
    template<typename T,typename S>
    struct less<Property<T, S> >
    {
        bool operator()(const Property<T, S>& lhs, const Property<T,S>& rhs) const
        {
            return lhs.p < rhs.p;
        }
    };
    }
    

    Another is to replace the default comparison type with a function with the correct signature, or a class that has an operator() defined with the correct signature. This is where things start to get ugly.

    // Comparison function
    template<typename T, typename S>
    bool property_less_function(const Property<T,S>& lhs, const Property<T,S>& rhs)
    {
        return lhs.p < rhs.p;
    }
    
    // Comparison functor
    template<typename T, typename S>
    struct PropertyLess
    {
        bool operator()(const Property<T,S>& lhs, const Property<T,S>& rhs) const
        {
            return lhs.p < rhs.p;
        }
    };
    
    int main()
    {
        // Set using comparison function. 
        // Have to pass the function pointer in the constructor so it knows
        // which function to call. The syntax could be cleaned up with some
        // typedefs.
        std::set<Property<std::string, std::string>, 
            bool(*)(const Property<std::string, std::string>&, 
                    const Property<std::string, std::string>&)> 
                set1(&property_less_function<std::string, std::string>);
    
        // Set using comparison functor. Don't have to pass a value for the functor
        // because it will be default constructed.
        std::set<Property<std::string, std::string>, PropertyLess<std::string, std::string> > set2;
    }
    

    Keep in mind that whatever less-than function you use, that function must define a strict weak ordering for your type.

    0 讨论(0)
  • 2020-12-02 03:31

    In order to insert something into std::set, you need to have operator< defined.

    For example this compiles fine on GCC 4.7.2:

    #include <iostream>
    #include <set>
    #include <vector>
    
    using namespace std;
    
    template <class T, class S> 
    class Property
    {
    public:
        pair<T,S> p;
        Property(T t, S s) { 
            p = make_pair(t,s);
        }
        bool operator<(const Property& p2) const {
            //Something naive..
            return p < p2.p; 
        }
    
    };
    
    int main()
    {
    set< Property<string, string> > properties;
    Property<string, string> name("name", "Andy");
    
    properties.insert(name);
    
    }
    

    An alternative would be to use std::unordered_set though that would require you to provide a hash for the key and defining operator==.

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