2010-04-15 74 views
9

我有一个小程序,我想执行测试的东西有问题的std ::地图和std ::对

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

的问题是,当我尝试编译它,我得到以下错误

$ 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&) 
$ 

我认为声明运营商<的关键将解决问题,但它仍然存在。

什么可能是错的?

在此先感谢。

+5

在C++中以双下划线开头的所有标识符,一个下划线跟着一个大写字母或一个下划线,然后在全局命名空间小写字母被保留用于执行。标识符'_pos'和'_val'应该被改变。 – 2010-04-15 07:17:13

+0

@大卫·罗德里格斯。谢谢,会做,并牢记在心。 – Tom 2010-04-15 13:22:50

回答

25

问题是这样的:

bool operator<(_pos& other) 

应该是这样的:

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

没有第一const,比较(ba < b)的右手侧不能const,因为没有const该函数可能会修改其参数。

没有第二const,比较(aa < b)的左手侧不能const,因为没有const函数可以修改this

从内部来看,地图的关键字总是const


应该指出,你应该更喜欢使用非成员函数。也就是说,更好的是一个自由功能:

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

在与你的类相同的命名空间。 (在我们的例子,只是它的下面。)


顺便说一句,在C++就没有必要用struct前缀结构类型变量的声明。这是完美的,首选:

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

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

(虽然你的类型名称在一个非正统的方式固然命名为:P)


最后,你应该更喜欢做对的make_pair效用函数:

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

它不需要写出对的类型,而且通常更容易阅读。 (特别是当更长的类型名称出现时。)

+0

感谢您的额外提示。 – Tom 2010-04-15 05:52:33

+0

@Tom:没问题,我添加了更多。 :P – GManNickG 2010-04-15 06:04:56

+0

在这种情况下,下标符号可能比直接使用插入符号要更简洁:'m [k1] = v1;米[K2] = V2;'。 – 2010-04-15 06:12:26

4

小于运算符的签名需要为bool operator<(const _pos& other) const,否则map不能在const函数中使用此运算符,因为此成员函数被声明为非const。

4

我认为你的运算符<的定义是错误的 - 右手边(在这种情况下的参数)应该被标记为const并且它应该是一个const成员函数,例如,

bool operator<(const _pos& other) const{ 

      return this->xi < other.xi; 
    }