使用成员函数指针作为键的C ++映射问题

时间:2014-02-13 08:48:59

标签: c++ map stl function-pointers comparison-operators

我用C ++编写,尝试在Ubuntu下编译,我遇到了使用函数指针作为键的映射的一些问题。当我定义地图时,我没有编译错误,但是当我尝试插入一个元素时,我得到一个相当罗嗦的

In file included from /usr/include/c++/4.6/string:50:0,
                 from /usr/include/c++/4.6/bits/locale_classes.h:42,
                 from /usr/include/c++/4.6/bits/ios_base.h:43,
                 from /usr/include/c++/4.6/ios:43,
                 from /usr/include/c++/4.6/ostream:40,
                 from /usr/include/c++/4.6/iostream:40,
                 from main.cpp:1:
/usr/include/c++/4.6/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = int (MyClass::*)()]’:
/usr/include/c++/4.6/bits/stl_tree.h:1277:4:   instantiated from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = int (MyClass::*)(), _Val = std::pair<int (MyClass::* const)(), std::vector<int> >, _KeyOfValue = std::_Select1st<std::pair<int (MyClass::* const)(), std::vector<int> > >, _Compare = std::less<int (MyClass::*)()>, _Alloc = std::allocator<std::pair<int (MyClass::* const)(), std::vector<int> > >]’
/usr/include/c++/4.6/bits/stl_map.h:518:41:   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::map<_Key, _Tp, _Compare, _Alloc>::value_type>::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = int (MyClass::*)(), _Tp = std::vector<int>, _Compare = std::less<int (MyClass::*)()>, _Alloc = std::allocator<std::pair<int (MyClass::* const)(), std::vector<int> > >, typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::map<_Key, _Tp, _Compare, _Alloc>::value_type>::other>::iterator = std::_Rb_tree_iterator<std::pair<int (MyClass::* const)(), std::vector<int> > >, std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<int (MyClass::* const)(), std::vector<int> >]’
main.cpp:36:51:   instantiated from here
/usr/include/c++/4.6/bits/stl_function.h:236:22: error: invalid operands of types ‘int (MyClass::* const)()’ and ‘int (MyClass::* const)()’ to binary ‘operator<’

以下是导致上述错误消息的示例:

#include <iostream>
#include <map>
#include <vector>

// class definition

class MyClass
{
    public:
            int f1(void);
            int f2(void);
};

int MyClass::f1(void)
{
    return 1;
}

int MyClass::f2(void)
{
    return 2;
}

using namespace std;

int main( int argc, char* argv[] )
{

    // define map
    map< int (MyClass::*)(void), vector<int> > myMap;
    vector<int> myVector;

    //myMap[ &MyClass::f1 ] = myVector;

    myMap.insert( make_pair( &MyClass::f1, myVector) );
    return 0;
}

可能是什么问题?我尝试使用insert和[] assign,我得到了同样的错误。浏览论坛,我发现this;但这可能是问题吗?我不认为我需要定义一个运算符“&lt;”对于函数指针(它们不应该像常规指针一样吗?)......还是我?

2 个答案:

答案 0 :(得分:1)

错误告诉你所有你需要知道的事情:

invalid operands of types ‘int (MyClass::* const)()’ and ‘int (MyClass::* const)()’ to binary ‘operator<’

您无法使用标准operator<比较成员函数指针,因此在声明地图时必须提供自定义比较器。

不幸的是,pointers to member functions cannot be compared for inequality,因此在这种情况下您无法定义比较运算符或使用std::map。我建议使用std::unordered_map,它只需要std::hash和相等比较,你可以做。请参阅here for hashing,此处查看equality comparison

答案 1 :(得分:-1)

您可以实现较少的模板专业化&lt; int(MyClass :: * const)()&gt;,如下所示:

typedef int (MyClass::*tMyClassMember)();
namespace std {
    template<>
    struct less<tMyClassMember>
    {
        bool operator()(const tMyClassMember& k1, const tMyClassMember& k2) const
        {
            auto p1 = reinterpret_cast<const intptr_t*>(&k1);
            auto p2 = reinterpret_cast<const intptr_t*>(&k2);
            return *p1 < *p2;
        }
    };
}

根据this question,可能有更好的方法来比较指针到成员,而不是将它们“转换”为整数,这是一个特定于实现的黑客攻击。 That questions包含有关如何执行此操作的详细信息。