2012-02-04 36 views
6

Tôi có một loạt các đối tượng trong một hệ thống phân cấp lớp và muốn tạo một tham chiếu std::map cho các đối tượng đó làm các phím trong bản đồ. Nó có vẻ như std::reference_wrapper sẽ là chính xác những gì là cần thiết cho việc này, nhưng tôi dường như không thể làm cho nó hoạt động. Những gì tôi đã cố gắng cho đến nay:Sử dụng std :: reference_wrapper làm khóa trong std :: map

class Object { // base class of my hierarchy 
    // most details unimportant 
public 
    virtual bool operator< (const Object &) const; // comparison operator 
}; 

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

auto it = table.find(object); 

table[object] = 42; 

table[object]++ 

Tuy nhiên, tôi luôn nhận được lỗi phần nào che khuất từ ​​trình biên dịch:

/usr/include/c++/4.5.3/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = std::reference_wrapper<const Object>]’: 
/usr/include/c++/4.5.3/bits/stl_tree.h:1522:38: instantiated from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::find(const _Key&) [with _Key = std::reference_wrapper<const Object>, _Val = std::pair<const std::reference_wrapper<const Object>, int>, _KeyOfValue = std::_Select1st<std::pair<const std::reference_wrapper<const Object>, int> >, _Compare = std::less<std::reference_wrapper<const Object> >, _Alloc = std::allocator<std::pair<const std::reference_wrapper<const Object>, int> >, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::reference_wrapper<const Object>, int> >]’ 
/usr/include/c++/4.5.3/bits/stl_map.h:697:29: instantiated from ‘std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::find(const key_type&)[with _Key = std::reference_wrapper<const Object>, _Tp = int, _Compare = std::less<std::reference_wrapper<const Object> >, _Alloc = std::allocator<std::pair<const std::reference_wrapper<const Object>, int> >, std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::reference_wrapper<const Object>, int> >, key_type = std::reference_wrapper<const Object>]’ 
testfile.cpp:39:31: instantiated from here 
/include/c++/4.5.3/bits/stl_function.h:230:22: error: no match for ‘operator<’ in ‘__x < __y’ 

Lỗi này có vẻ được nói rằng nó không thể so sánh hai std::reference_wrapper<const Object> đối tượng, nhưng có vẻ như có thể - std::reference_wrapper có một toán tử chuyển đổi có thể chuyển đổi nó thành một số T& (const Object & tại đây), và Object có một số operator <, vậy tại sao nó không hoạt động?

Nếu nó hoạt động và đây chỉ là lỗi trong g + +? Hoặc là thứ gì đó đang diễn ra?

+0

Không 'std :: ref (đối tượng) dalle

Trả lời

5

Dường như nó sẽ hoạt động nếu bạn thực hiện toán tử so sánh một hàm miễn phí (có thể gọi hàm thành viên ảo).

Nếu đó là hàm thành viên, a < b thực sự có nghĩa là a.operator<(b); và chuyển đổi ẩn sẽ không được xem xét cho đối số bên trái.

1

Trên Visual Studio 11 Beta, tôi nhận được cùng một vấn đề. Sử dụng phiên bản miễn phí gọi nhà điều hành < giải quyết được sự cố.

#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; 
} 
3

Theo mặc định std::less<std::reference_wrapper<const Object>> được sử dụng nhưng không chuyển tiếp operator<() đến loại cơ bản.

Tùy chọn đơn giản và concisest để giải quyết vấn đề của bạn là xác định std::less<const Object> (hoặc std::greater<const Object>) trong định nghĩa bản đồ như thế này:

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

Nó sẽ làm việc một cách chính xác và như mong đợi do implicit conversion of std::reference_wrapper to T&implicit constructor of std::reference_wrapper.

Example.

Các vấn đề liên quan