如何在C++中定义成员函数指针到字符串的映射?
解决成员函数指针作为std::map键的问题
你遇到的问题很典型:std::map默认要求键类型必须支持<运算符,但C++标准并没有强制规定成员函数指针必须实现这个运算符——不同编译器对成员函数指针的内部表示可能不同(比如有些会用包含额外信息的结构体,尤其是虚函数指针),所以编译器没法自动生成合法的<逻辑,这就是报错的核心原因。
下面给你三种可行的解决方案,按实用性和兼容性排序:
1. 自定义比较器给std::map
我们可以自己写一个比较结构体,把成员函数指针转换成可比较的整数类型(比如uintptr_t)来实现大小比较。虽然这种转换是实现定义的行为,但主流编译器(GCC、Clang、MSVC)都支持,完全能满足日常开发需求。
修改后的代码示例:
#include <map> #include <string> #include <cstdint> // 用于uintptr_t class foo; typedef void (foo::*fooFunc)(); // 自定义比较器 struct FooFuncComparator { bool operator()(fooFunc a, fooFunc b) const { // 将成员函数指针转换为无符号整数后比较 return reinterpret_cast<uintptr_t>(a) < reinterpret_cast<uintptr_t>(b); } }; class foo { public: foo() { myMap[&foo::func] = "example function"; // 注意:成员函数指针必须用&类名::成员函数名的形式获取 } void func() {}; // 使用自定义比较器的map std::map<fooFunc, std::string, FooFuncComparator> myMap; };
2. 使用std::unordered_map(无序映射)
如果你不需要map保持有序,用std::unordered_map会更高效,只需要自定义哈希函数即可(成员函数指针的==是标准支持的,相等判断可以直接用默认逻辑):
#include <unordered_map> #include <string> #include <cstdint> #include <functional> // 用于std::hash class foo; typedef void (foo::*fooFunc)(); // 自定义哈希函数 struct FooFuncHash { size_t operator()(fooFunc func) const { return std::hash<uintptr_t>()(reinterpret_cast<uintptr_t>(func)); } }; class foo { public: foo() { myMap[&foo::func] = "example function"; } void func() {}; std::unordered_map<fooFunc, std::string, FooFuncHash> myMap; };
3. 使用间接标识(最标准安全的方案)
如果不想依赖编译器相关的指针转换,可以给每个成员函数分配一个唯一的标识(比如枚举值),用这个标识作为map的键,同时存储成员函数指针和对应的字符串:
#include <map> #include <string> #include <utility> // 用于std::pair class foo; typedef void (foo::*fooFunc)(); // 给每个成员函数分配唯一ID enum class FooFuncID { Func }; class foo { public: foo() { myMap[FooFuncID::Func] = {&foo::func, "example function"}; } void func() {}; // map的键是枚举ID,值是成员函数指针+字符串的配对 std::map<FooFuncID, std::pair<fooFunc, std::string>> myMap; };
这种方案完全符合C++标准,没有任何实现定义的行为,适合对兼容性要求极高的场景。
内容的提问来源于stack exchange,提问作者q.t.f.
相关产品推荐
相关产品推荐

