两者之间的转换略有不同 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;
}
我有一个 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;
}