2010-04-15 23 views
9

tôi có một chương trình nhỏ, tôi muốn thực hiện để kiểm tra một cái gì đóVấn đề với std :: bản đồ và std :: cặp

#include <map> 
#include <iostream> 
using namespace std; 

struct _pos{ 
     float xi; 
     float xf; 

     bool operator<(_pos& other){ 

       return this->xi < other.xi; 
     } 
}; 

struct _val{ 

     float f; 
}; 

int main() 
{ 
     map<_pos,_val> m; 

     struct _pos k1 = {0,10}; 
     struct _pos k2 = {10,15}; 

     struct _val v1 = {5.5}; 
     struct _val v2 = {12.3};                 

     m.insert(std::pair<_pos,_val>(k1,v1)); 
     m.insert(std::pair<_pos,_val>(k2,v2)); 

     return 0; 
} 

Vấn đề là khi tôi cố gắng để biên dịch nó, tôi nhận được lỗi sau

$ g++ m2.cpp -o mtest 
In file included from /usr/include/c++/4.4/bits/stl_tree.h:64, 
       from /usr/include/c++/4.4/map:60, 
       from m2.cpp:1: 
/usr/include/c++/4.4/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = _pos]’: 
/usr/include/c++/4.4/bits/stl_tree.h:1170: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = _pos, _Val = std::pair<const _pos, _val>, _KeyOfValue = std::_Select1st<std::pair<const _pos, _val> >, _Compare = std::less<_pos>, _Alloc = std::allocator<std::pair<const _pos, _val> >]’ 
/usr/include/c++/4.4/bits/stl_map.h:500: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [with _Key = _pos, _Tp = _val, _Compare = std::less<_pos>, _Alloc = std::allocator<std::pair<const _pos, _val> >]’ 
m2.cpp:30: instantiated from here 
/usr/include/c++/4.4/bits/stl_function.h:230: error: no match for ‘operator<’ in ‘__x < __y’ 
m2.cpp:9: note: candidates are: bool _pos::operator<(_pos&) 
$ 

Tôi nghĩ rằng việc khai báo toán tử < trên khóa sẽ giải quyết được sự cố, nhưng vẫn ở đó.

Điều gì có thể sai?

Xin cảm ơn trước.

+5

Trong C++ tất cả số nhận dạng bắt đầu bằng dấu gạch dưới kép, một dấu gạch dưới duy nhất theo sau là chữ cái viết hoa hoặc dấu gạch dưới duy nhất theo sau là một chữ cái thường trong không gian tên chung được dành riêng cho việc triển khai. Các định danh '_pos' và' _val' phải được thay đổi. –

+0

@David Rodríguez. Cảm ơn, sẽ làm và ghi nhớ điều đó. – Tom

Trả lời

25

Vấn đề là thế này:

bool operator<(_pos& other) 

nên là thế này:

bool operator<(const _pos& other) const { 
//    ^^^^    ^^^^^ 

Nếu không có sự const đầu tiên, phía bên tay phải của sự so sánh (b trong a < b) không thể const, kể từ nếu không có const, hàm có thể sửa đổi đối số của nó.

Nếu không có thứ hai const, phía bên tay trái của sự so sánh (a trong a < b) không thể const, vì không const chức năng có thể sửa đổi this.

Nội bộ, khóa của bản đồ luôn là const.


Cần lưu ý rằng bạn nên sử dụng các chức năng không phải là thành viên. Tức là, tốt hơn là một chức năng miễn phí:

bool operator<(const _pos& lhs, const _pos& rhs) 
{ 
    return lhs.xi < rhs.xi; 
} 

Trong cùng một không gian tên như lớp học của bạn. (Ví dụ của chúng tôi, chỉ cần bên dưới nó.)


Bằng cách này, trong C++ không có nhu cầu tiền tố tuyên bố của một biến kiểu struct với struct. Đây là hoàn hảo, và ưa thích:

_pos k1 = {0,10}; 
    _pos k2 = {10,15}; 

    _val v1 = {5.5}; 
    _val v2 = {12.3}; 

(Mặc dù tên loại của bạn đang phải thừa nhận là tên một cách không chính thống:. P)


Cuối cùng, bạn nên chọn chức năng make_pair tiện ích để làm cặp:

m.insert(std::make_pair(k1,v1)); 
    m.insert(std::make_pair(k2,v2)); 

Nó giúp bạn không phải viết loại cho cặp và nói chung dễ đọc hơn. (Đặc biệt khi tên loại dài hơn xuất hiện.)

+0

Cảm ơn bạn đã thêm mẹo. – Tom

+0

@Tom: Không sao, tôi đã thêm nhiều hơn. : P – GManNickG

+0

Trong trường hợp này, ký hiệu chỉ số có thể nhỏ hơn so với chèn trực tiếp: 'm [k1] = v1; m [k2] = v2; '. –

4

Chữ ký của toán tử nhỏ hơn cần phải là bool operator<(const _pos& other) const, nếu không bản đồ không thể sử dụng toán tử này trong các hàm const vì hàm thành viên này được khai báo là không phải là const.

4

Tôi nghĩ rằng định nghĩa của toán tử < là sai - bên tay phải (đối số trong trường hợp này) phải được đánh dấu const và nó phải là hàm thành viên const, ví dụ:

bool operator<(const _pos& other) const{ 

      return this->xi < other.xi; 
    }