I want to use std::function<void()> as a typename in initializing a map:
void warning() {}
void error()
{
exit(1);
}
std::map<std::string, std::function<void()>> msgtypes = {
{ "WARNING", warning },
{ "ERROR", error }
};
But it’s not working: error: could not convert ‘{{"WARNING", ((kc::kcmessage*)this)->kc::kcmessage::warning}, {"ERROR", ((kc::kcmessage*)this)->kc::kcmessage::error}}’ from ‘<brace-enclosed initializer list>’ to ‘std::map<std::__cxx11::basic_string<char>, std::function<void()> >’ (<brace-enclosed initializer list>)
Edit
Due to the comments, it works (and I tested myself). I think the problem is I’m using that in a class and namespace; updated (it doesn’t works):
namespace kc
{
class kcmessage
{
private:
std::string value;
void warning() {}
void error()
{
exit(1);
}
std::map<std::string, std::function<void()>> msgtypes = {
{ "WARNING", warning },
{ "ERROR", error }
};
int msgtype;
};
}
>Solution :
If you want to access a member function ( non static ) you have to bind the method to the instance of the class. For that you can use std::bind but it is much easier to simply use a lambda for that purpose.
#include <functional>
#include <map>
#include <string>
#include <iostream>
namespace kc
{
class kcmessage
{
private:
std::string value;
void warning() {std::cout << "Waring called!"<<std::endl;}
void error()
{
std::cout << "Error called" << std::endl;
//exit(1);
}
std::map<std::string, std::function<void()>> msgtypes = {
{ "WARNING", [this](){ warning();} },
{ "ERROR", [this](){ error();} }
};
int msgtype;
public:
void CallAll()
{
for( auto& el: msgtypes)
{
el.second();
}
}
};
}
int main()
{
kc::kcmessage{}.CallAll();
}
Execute it here
You can make your methods also static ones, but in this case you can’t any longer access your member data if needed which is typically the case.