两者之间的转换略有不同 std::map

Cast between two slightly different std::map


我有一个 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等,对于classSomeClass,每一个都不一样,就是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 没有真正使用回调,但使用 [=45 中的其他两个值=]{$i}, i=1...n.


问题是无论我多么努力地尝试在两个映射之间转换,编译器(符合 C++11 的 GCC)总是抱怨。


如有任何想法,我们将不胜感激。

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

如果你能控制你的SomeClass, SomeClass2...,你可以使用继承来解决这个问题:

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

typedef void (BaseClass::*callback_f)();
....

如果您需要将所有映射传递给一个函数,那么所有映射必须是完全相同的类型(但您已经知道这一点)。

稍加重新设计即可满足您的需求。

与其定义您的映射来保存特定的函数指针签名,不如简单地定义一个保存多态可调用对象的映射类型 - 这样的对象是 std::function<>。

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