在两个略有不同的std ::地图之间投射

Cast between two slightly different std::map

本文关键字:std 地图 之间 两个      更新时间:2023-10-16


我有一个std ::地图定义如下:

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等


我的需求是将所有这些映射传递给一个单个函数,该函数必须具有单个签名,而不论其地图如何,所以我定义了一个通用地图:

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}的其他两个值,&nbsp;i = 1 ... n


问题在于我尝试在两个地图之间施放多么努力,编译器(C 11兼容的GCC)总是抱怨。


任何想法都将不胜感激。

如果您需要将所有地图传递给一个函数,则所有地图必须完全相同(但是您已经知道)。

一些重新设计应该给您想要的东西。

而不是定义映射以保存特定函数指针签名,只需定义一个包含多态性可可对象的一个地图类型 - 这样的对象是std :: function&lt;>。

完整的可编译示例(请记住启用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;
}

如果您对someclass,someclass2 ...,您可以使用继承来解决此问题:

class BaseClass
{
public:
  virtual ~BaseClass(){}
  virtual void f() = 0;
};
class SomeClass : public BaseClass {...};
class SomeClass2 : public BaseClass {...};
typedef void (BaseClass::*callback_f)();
....

解决方案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的建议进行编辑。