我有一个std :: map定义如下:
typedef void (SomeClass::*callback_f)();
typedef std::pair<std::string, callback_f> my_pair;
typedef std::map<char,my_pair> my_map1;
这些定义有多个,所以有my_map1,my_map2等,并且它们中的每一个都与SomeClass类不同,后者是SomeClass,SomeClassTwo等。
我需要将所有这些地图传递给单个函数,无论地图如何,都必须有一个单一的签名,所以我定义了一个通用的地图:
typedef std::pair<std::string ,void(*)(void)> my_generic_pair;
typedef std::map<char, my_generic_pair> my_generic_map;
一个将其作为参数的函数:
void myGenericFunction(my_generic_map lmap);
myGenericFunction 不会真正使用回调,但使用 my_map {$ i}中的其他两个值,i = 1 ... n
问题是无论我试图在两个地图之间施放多么努力,编译器(符合C ++ 11的GCC)总是抱怨。
非常感谢任何想法。
答案 0 :(得分:3)
如果您需要将所有地图传递给单个函数,那么所有地图必须完全相同(但您已经知道了)。
进行一些重新设计可以给你你想要的东西。
不是定义地图以保存特定的函数指针签名,而是简单地定义一个包含多态可调用对象的地图类型 - 这样的对象是std :: function&lt;&gt;。
完全可编译的示例(记得启用c ++ 11):
#include <iostream>
#include <functional>
#include <utility>
#include <string>
#include <map>
// callback_f is any callable that takes no parameters
typedef std::function<void()> callback_f;
typedef std::pair<std::string, callback_f> my_pair;
typedef std::map<char,my_pair> universal_map;
using namespace std;
struct SomeClass {
static void callme_for_all() {
cout << "SomeClass Hears You";
}
};
struct SomeOtherClass {
SomeOtherClass(string name)
: _name { move(name) }
{}
void callme_for_each() const {
cout << "I am called " << _name;
}
private:
string _name;
};
void handle_map(const universal_map& m) {
for (const auto& item : m) {
cout << item.first << ":" << item.second.first << ":";
item.second.second();
cout << endl;
}
}
int main()
{
cout << "Hello World" << endl;
SomeClass a,b,c;
SomeOtherClass x { "x" }, y { "y" }, z { "z" };
universal_map map_someclass {
{ 'A', { "chicken", std::bind(&SomeClass::callme_for_all) } },
{ 'B', { "donkey", std::bind(&SomeClass::callme_for_all) } },
{ 'C', { "turkey", std::bind(&SomeClass::callme_for_all) } },
};
universal_map map_someotherclass {
{ 'A', { "pig", std::bind(&SomeOtherClass::callme_for_each, &x) } },
{ 'B', { "cat", std::bind(&SomeOtherClass::callme_for_each, &y) } },
{ 'C', { "dog", std::bind(&SomeOtherClass::callme_for_each, &z) } },
};
cout << "map for SomeClass - calling static methods" << endl;
handle_map(map_someclass);
cout << endl;
cout << "map for SomeOtherClass - calling instance methods" << endl;
handle_map(map_someotherclass);
return 0;
}
答案 1 :(得分:1)
解决方案1:
template<typename T>
void myGenericFunction(std::map < char, std::pair < std::string, T > > lmap);
解决方案2(仅当您因任何原因无法使用模板和重载时):
enum MapType {MY_MAP1, MY_MAP2, ...};
void myGenericFunction(void* lmap, MapType typeOfLmap)
{
switch(typeOfLmap)
{
case MY_MAP1:
//do something with ((my_map1*)lmap)
break;
...
}
}
编辑:根据@TonyD的建议进行编辑。
答案 2 :(得分:1)
如果你可以控制SomeClass,SomeClass2 ......,你可以使用继承来解决这个问题:
class BaseClass
{
public:
virtual ~BaseClass(){}
virtual void f() = 0;
};
class SomeClass : public BaseClass {...};
class SomeClass2 : public BaseClass {...};
typedef void (BaseClass::*callback_f)();
....