I'm tried to make a map to class methods using C++11's function.
The C-Style function pointers:
Method:
void MyClass::MyMethod(void*);
Map declare:
std::map<int, void (MyClass::*)(void*)> mapIdToMethod;
Map insert:
mapIdToMethod.insert(std::make_pair(2, &MyClass::MyMethod));
Method call:
MyClass mc;
(mc.*mapIdToMethod.at(1))(nullptr);
The code above is worked, But how can I convert it to use C++11's function?
What i'm tried:
Map declare:
std::map<int, function<void(void*)>> mapIdToMethod;//The map declare
Now, how can I insert and call the method on this map?
Probably not as efficient as the original but maybe easier to read:
std::map<int, std::function<void (MyClass&,void*)>> mapIdToMethod;
mapIdToMethod.emplace(2, [](MyClass& c,void* p){ c.MyMethod(p);});
// alternatively:
using std::placeholders::_1;
using std::placeholders::_2;
mapIdToMethod.emplace(2,std::bind(&MyClass::MyMethod,_1,_2));
MyClass mc;
mapIdToMethod.at(2)(mc, nullptr);
I am also a fan of function over C-style pointers, but it's important that you recognize that the analog for void (MyClass::*)(void*) is function<void(MyClass&, void*)> not function<void(void*)>. So you could replicate what you've already have going in MapIdToMethod with:
map<int, function<void(MyClass&, void*)>> bar;
You could insert to this the same way as you inserted to MapIdToMethod (bar.insert(make_pair(2, &MyClass::MyMethod)), but you could also use mem_fn, which wouldn't have been possible to use when inserting to MapIdToMethod:
bar.insert(make_pair(2, mem_fn(&MyClass::MyMethod)));
Now, to answer your question. Given:
map<int, function<void(void*)>> foo;
You can insert member functions which take a void* and don't return anything, but only if you already have the object on which you wish to make the calls constructed. You can do that using bind:
MyClass mc;
foo.insert(make_pair(2, bind(&MyClass::MyMethod, mc, placeholders::_1)));
Live Example
Related
I have a map of structs that holds several named values like this:
struct MyData {
MyType dataA;
std::string dataB;
int dataC;
};
typedef std::pair<std::string, MyData> PairType;
std::map<PairType::first_type, PairType::second_type> dataMap;
This is defined in a header file of a compilation unit that calls a function from a library.
Because the library function does not know about my type definitions, I can't pass dataMap directly.
The function only actually needs the dataA struct member and already knows about MyType, so I could pass a std::map<std::string, MyType> instead.
Whats the most elegant way of cutting just the data I need from the map of structs and save it into a new map with the same keys but only the type and values from dataA?
Preferably for C++0x without usage of boost or other external libraries, but solutions for newer standards are also welcome for educational purposes.
I'm basically looking for an equivalent of Python's
newDict = {key:value.dataA for (key,value) in oldDict.items()}
You can use a ranged based for loop to really easily make a copy. That would look like
std::map<std::string, MyType> my_type_map;
for (const auto& pair : dataMap)
{
my_type_map.emplace(pair.first, pair.second.dataA);
}
If you want this as a single expression, you are going to need something like boost::transform_iterator, either by including that, or writing an iterator yourself.
Given a conversion function (or equivalent lambda)
std::pair<std::string, MyType> convert(PairType& pair){
return { pair.first, pair.second.dataA };
};
You can declare newDict and populate it
/* can be const */ std::map<std::string, MyType> newDict {
boost::make_transform_iterator(oldDict.begin(), convert),
boost::make_transform_iterator(oldDict.end(), convert)
};
Or you can use a view type
auto newDict = boost::copy_range<std::map<std::string, MyType>>(oldDict | std::ranges::views::transform(convert));
I have the following code in myclass.h file:
typedef std::unordered_set< int, int> Parameters;
class MyClass
{
public:
void myFunction();
private:
Parameters* m_params;
}
Then, myFunction looks as follows:
void MyClass::myFunction()
{
...
m_params->emplace(1,1);
}
When I try to compile, I get:
term does not evaluate to a function taking 1 arguments
If I comment the emplace line, the error disappears. However, I don't find any misuse related to this function signature:
http://en.cppreference.com/w/cpp/container/unordered_map/emplace
Any help would be much appreciated.
Simple typo: You used std::unordered_set in your code, but you meant std::unordered_map.
Your implementation doesn't recognise any error setting Hash to int in the std::unordered_set template until you try to put something into the container. Then it tries to hash the input, and realises it can't use an int as a function.
I would like to know how to fill this type of map and mainly the way to access to the function pointer.
The map :
enum enum1
{
val11,
val12,
val13
};
enum enum2
{
val21,
val22,
val23
};
typedef void(MyClass::*funcPtr)();
std::map<std::pair<enum1, enum2>, funcPtr> map;
I fill it like this, it seems to work:
map.insert(std::make_pair(std::make_pair(val11, val21), &MyClass::init));
But I can't access to the function like this:
map[std::make_pair<val11, val21>]();
What am I doing wrong?
You are using the wrong parentheses with make_pair and need to call the member function on some instance of MyClass (using the .* or ->* operators):
MyClass obj;
(obj.*map[std::make_pair(val11, val21)])();
I am trying to create a simple manager that will map error codes to functions. But since a map copies the values and a signal is noncopyable that is not a solution. I cannot use a map of shared_ptr pointers since the * operator is blocked in boost::function.
Which collection should I use to store this?
typedef boost::function<bool (shared_ptr<EngineEvent> event,long timeSinceEvent)> EngineErrorHandler;
typedef boost::signal<bool ( EngineErrorHandler )> ErrorSignal;
typedef std::map<EventErrorType,ErrorSignal> ErrorHandlers;
class ServiceErrorManager {
public:
static ServiceErrorManager* getInstance();
void registerErrorHandler(EngineErrorHandler& handler,EventErrorType subScribeTo);
void signalEngineEventfail(shared_ptr<EngineEvent> event);
private:
static ServiceErrorManager* m_pInstance;
ErrorHandlers errorTypeToSignal;
ServiceErrorManager();
~ServiceErrorManager();
};
}
You could always store everything into a struct and store shared_ptr or unique_ptr objects inside a map or set using a custom predicate. This seems like it would make your code a bit more self-explanatory as well.
I've got a static class member which is some container, like
(Foo.h)
class Foo
{
...
private:
static list<string> s_List;
}
I need to populate the list with a number of specific values. Actually it should be also const, but that might overcomplicate the problem further.
All the class member functions are static, so initializing it in a constructor doesn't make sense.
a common solution is to do something like this:
// header
class Foo
{
...
private:
static list<string> s_List;
}
// cpp
list<string> init()
{
list<string> tmp;
... fill tmp with strings
return tmp;
}
list<string> Foo::s_List(init());
the other method is like Neil Butterworth suggested.
Another alternative is to create a simple initialiser class:
list <string> Foo::s_List;
struct Init {
Init() {
Foo::s_List.insert("apple");
Foo::s_List.insert("bannana");
Foo::s_List.insert("grapes");
}
};
static Init doInit;
Note that, as the list is private, this will probably require you to make Init a friend of Foo. It's also often convenient to make such classes be contained by the class they are initialising.
However, I just re-read your question and another thought occurs - if the list is const, you will presumably not be changing it, in which case a simple array of strings, initialised with the strings in sorted order may be a better solution. It will certainly be faster to search (using std::binary_search) than a list, and can of course be easily initialised.
If your compiler supports C++0x, this is actually trivial to accomplish.
#include <iostream>
#include <list>
class Foo
{
public:
static std::list<std::string> s_List;
};
std::list<std::string> Foo::s_List = {"hello", "world", "asdf", "qwerty"};
int main()
{
for(const std::string& str : Foo::s_List)
std::cout << str << std::endl;
return 0;
}
This works for both const and non-const static members. I've tested this snippet with clang-4.2, gcc-4.7, gcc-4.6, and gcc-4.5. Gcc-4.5 does not support the updated for syntax, so you'd have to use a traditional for loop with iterators. Also, don't forget to pass the -std=c++0x flag to the compiler. I'm reasonably confident Visual Studio supports this as well, but I don't know for sure and don't know which versions.
It depends on what values you need to put in that list. Are they static or do they require some form of computation?
If they are static, you can do this:
namespace {
const char* const initVals[] = { "A", "B", "C" };
}
list<string> Foo::s_list(initVals, initVals + 3);
one possible solution would be to use an accessor method that checks to see if it is initialized, and does so if it isn't.
The ways I(the author of the question) have vainly tried to do this.
I tried to do smth like (in Foo.cpp):
list<string> Foo::s_List = list<string>();
Foo::s_List.insert("apple");
Foo::s_List.insert("bannana");
Foo::s_List.insert("grapes");
But that gives a compiler error.
Then I thought of making an Initialize() method and calling it right from the code
void Foo::Initialize()
{
s_List.insert("rats");
s_List.insert("cats");
}
Foo::Initialize();
// error: compiler considers it to be a redefenition of the method, not a call.
The only viable idea left (havent yet tried) would be to check if the list is empty in each method that uses it, and if it's the case, call Initialize(). But that's ugly!