Using std::reference_wrapper as the key in a std::map

前端 未结 3 593
再見小時候
再見小時候 2021-01-12 01:18

I have a bunch of objects in a class hierarchy and would like to make a std::map using references to those objects as the keys in the map. Its seems like

相关标签:
3条回答
  • On Visual Studio 11 Beta, I get the same problem. Using the free version which calls the < operator solves the problem.

    #include<map>
    #include<iostream>
    using namespace::std;
    
    class Object { 
        int _n1;
    public:
    
        Object(int n = 0):_n1(n){};
        bool operator < (const Object& rhs) const {return this->_n1 < rhs._n1;} 
        friend ostream &operator << (ostream &stream, const Object& o) { stream << o._n1 << " "; return stream;}
    };
    
    struct ObjectLess{
    
        bool operator()(const Object& lhs, const Object& rhs) const 
        {
            return lhs<rhs;
        }
    };
    
    int main(int argc, char* argv[])
    {
        //This does not compile
        //std::map<std::reference_wrapper<const Object>, string> table;
    
        //Using the free function works
        std::map<std::reference_wrapper<const Object>, string, ObjectLess> table;
    
        Object a(1);
        Object b(2);
        Object c(3);
    
    
        table[a]="One";
        table[c]="Three";
        table[b]="Two";
    
        for(auto y: table){
        cout << y.first << " " << y.second.c_str() << std::endl;
    }
    
    
        return 0;
    }
    
    0 讨论(0)
  • 2021-01-12 02:21

    By default std::map uses std::less<std::reference_wrapper<const Object>> as Compare, but std::reference_wrapper<T> doesn't forward operator<() to the underlying type T.

    The simplest and concisest option to solve your problem is to define std::less<const Object> (or std::greater<const Object>) in the map definition like this:

    std::map<std::reference_wrapper<const Object>, int, std::less<const Object>> table;
    

    It will work correctly and as expected due to implicit conversion of std::reference_wrapper to T& and implicit constructor of std::reference_wrapper.

    Example.

    0 讨论(0)
  • 2021-01-12 02:23

    It seems that it would work if you made the comparison operator a free function (that perhaps calls a virtual member function).

    If it is a member function, a < b really means a.operator<(b); and implicit conversions are not considered for the left-side argument.

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