C++ Map of string and member function pointer - c++

Hey so I am making a map with string as the key and a member function pointer as the value. I can't seem to figure out how to add to the map, this doesn't seem to be working.
#include <iostream>
#include <map>
using namespace std;
typedef string(Test::*myFunc)(string);
typedef map<string, myFunc> MyMap;
class Test
{
private:
MyMap myMap;
public:
Test(void);
string TestFunc(string input);
};
#include "Test.h"
Test::Test(void)
{
myMap.insert("test", &TestFunc);
myMap["test"] = &TestFunc;
}
string Test::TestFunc(string input)
{
}

See std::map::insert and std::map for value_type
myMap.insert(std::map<std::string, myFunc>::value_type("test", &Test::TestFunc));
and for operator[]
myMap["test"] = &Test::TestFunc;
You cannot use a pointer to member function without an object. You can use the pointer to member function with an object of type Test
Test t;
myFunc f = myMap["test"];
std::string s = (t.*f)("Hello, world!");
or with a pointer to type Test
Test *p = new Test();
myFunc f = myMap["test"];
std::string s = (p->*f)("Hello, world!");
See also C++ FAQ - Pointers to member functions

Related

How to use string to call function in a class?

I hope to use map library to call a function by a string with the function name, I've tested the following example and everything are working well.
#include <string>
#include <iostream>
using namespace std;
typedef void (*pFunc)();
map<string, pFunc> strFuncMap;
void func1()
{
printf("this is func1!\n");
}
void buildMap()
{
strFuncMap["func1"] = &func1;//
}
void callFunc(const std::string& str)
{
(*strFuncMap[str])();
}
int main()
{
buildMap();
callFunc("func1");
return 0;
}
However, as I define all these things in a class, there is a compiler error occur:
#include <map>
#include <string>
#include <iostream>
using namespace std;
class theClass {
public:
typedef void (*pFunc)();
map<string, pFunc> strFuncMap;
void func1()
{
printf("this is func1!\n");
}
void buildMap()
{
strFuncMap["func1"] = &func1;// a value of type cannot be assigned to an entity of type
}
void callFunc(const std::string& str)
{
(*strFuncMap[str])();
}
};
int main()
{
theClass a;
a.buildMap();
a.callFunc("func1");
return 0;
}
I've tried to solve this problem for a couple of hours. Or is there any other way to use string to call function in a class? I will very appreciate if someone can help me. THANKS!!
Your code doesn't work because func1 is a member function and the syntax for member functions is different.
You need a map of member function pointers (offsets)
typedef void (theClass::*pFunc)();
map<string, pFunc> strFuncMap;
Then you can store the pointer with
strFuncMap["func1"] = &theClass::func1;
And you need an object to call a member function
(this->*strFuncMap[str])();
The final code:
#include <map>
#include <string>
#include <iostream>
using namespace std;
class theClass {
public:
typedef void (theClass::*pFunc)();
map<string, pFunc> strFuncMap;
void func1()
{
printf("this is func1!\n");
}
void buildMap()
{
strFuncMap["func1"] = &theClass::func1;
}
void callFunc(const std::string& str)
{
(this->*strFuncMap[str])();
}
};
int main()
{
theClass a;
a.buildMap();
a.callFunc("func1");
return 0;
}
typedef void (*pFunc)();
This declares pFunc to be the type of function pointers. That is, the type of pointers to functions which exist at the top-level. This excludes member functions, lambda functions, and functors. Consider
using pFunc = std::function<void()>
Now your type will correctly accept anything that can reasonably be interpreted as a callable object. Note that member functions still need to be wrapped in a lambda, since you're closing around this.
strFuncMap["func1"] = [this]() { this->func1(); };

How to access the type inside a std::variant?

I need to build a vector of a class that can have multiple type like this:
#include <variant>
#include <vector>
#include "Field.h"
using namespace std;
int main()
{
variant <int, float> v;
vector <variant<Field<int>, Field<string>, Field<float>>> fdList;
fdList[0].getName();
}
And this is header file Field.h:
#pragma once
#include <string>
#include <vector>
using namespace std;
template<class T>
class Field
{
public:
Field();
Field(string);
void setName(string);
string getName();
bool isPrime();
void toPrime();
void toForeign(Field);
~Field();
private:
string FD_Name;
vector <T> records;
bool isPrimeK = false;
string message;
};
template<class T>
string Field<T>::getName()
{
return FD_Name;
}
When I try to access getName() function, Visual Studio keeps giving me the following message error:
E0135 class "std::variant<Field, Fieldstd::string, Field>" has no member "getName"
C2039 'getName': is not a member of 'std::variant<Field,Fieldstd::string,Field>'
But it works just fine, if I define my vector like this:
vector <Field<int>> fdList;
fdList[0].getName();
How can I fix this?
For any issue about standard library, I recommend you to check document first.
You can see here about how to use std::variant.
In short, you cannot access the content in your std::variant like that because its type is std::variant but not the types you store in it. For your case, I think you may want to check what's inside first by calling std::variant::index() method, then get the value by calling std::get.
Calling a method on variant doesn't automatically call the method of the active alternative of variant. You'll have to visit the active alternative and invoke the corresponding handler. In your case, since you want to handle all of the potential active alternatives the same way, you can do:
std::visit([](const auto& field) {
field.getName();
// ...
}, fdList[0]);
Alternatively, you can wrap the variant in something like:
struct AnyField {
string getName() const {
return std::visit([](const auto& field) { return field.getName(); }, v);
}
std::variant<Field<int>, Field<string>, Field<float>> v;
};
then use them like you wanted to:
vector<AnyField> fdList;
fdList[0].getName();

C++ Creating a function that is being pointed to as an argument

So this is confusing to explain, but I will try my best.
I have a function one of my classes that takes a function pointer as an argument, and what I would like to do is define the function as part of the argument. ie:
object->setFunctionPointer({string a = ""; return a;});
Is this possible? if so, what is the proper syntax of this?
In C++11, you can do it. You can use C++ lambda (anonymous functions).
See the sample code at http://ideone.com/8ZTWSU
#include <iostream>
using namespace std;
typedef const char * (*funcptr)();
funcptr s;
void setFuncPtr(funcptr t)
{
s = t;
}
int main() {
// your code goes here
setFuncPtr([]{return "Hello \n"; });
printf("%s\n", s());
return 0;
}
If we are talking about C++ you should use std::function and not function pointers. Unless you are interfacing with C APIs.
class Foo{
SetFunc(std::function<void(int)> func)
{
m_func = func;
}
private:
std::function<void(int)> m_func;
};
If your function is a member of a class, you cannot take an ordinary function pointer to store its address. What you need is a delegate; which are specialised function pointers for methods. Search the internet for C++ delegate and you should find numerous examples.
(Note: maybe there is an exception for static methods; I don't remember.)
Here is a complete example. Since c++11 this is the way to go:
#include<functional>
#include<string>
#include<iostream>
using namespace std;
class Object
{
public:
void setFunctionPointer(function<string(void)> function)
{
m_function = function;
}
string run()
{
return m_function();
}
private:
function<string(void)> m_function;
};
int main(int argc, char**argv)
{
Object *object = new Object;
object->setFunctionPointer([]{string a = "FOO"; return a;}); // here is the function assignment
cout << object->run() << endl;
delete object;
}
When run this prints FOO to stdout.

how can i change value type of a object in c++

I have an issue in assigning value to a object.
my object definition says:
class myobject {
public:
var_type type;
union value_type value;
myobject(int value);
myobject(string value);
...
};
enum var_type {
var_int,
var_str,
var_float
};
union value_type {
int;
real;
string;
};
myobject* object = get_object("name");
//here i need to change its value, i dont have any setvalue function.
Now in some other file i need to update the value of myobject, but i dont know the value type. say initial value_type is int, and my function assigns it a string, i get absurd value at doign GetValue().
what should be more efficient way to get the value type of the object, change my string value to the old value type it supporting and modified it. I cant change in the definition class of myobject.
Thanks
Ruchi
With limited information provided in your question I assume that you want to change the value of your pointer "object" depending on input which could string or int or something else.
Check this program, I make use of "boost::any" and typeid. Review this option and test it in your program. Else do explicitly explain with some code example what you want to achieve.
Also union with string would give you compile problems? Is it not?
#include <iostream>
#include <string>
#include <typeinfo>
#include <boost/any.hpp>
#include <boost/unordered_map.hpp>
#include<list>
using namespace std;
class myobject {
public:
myobject(int value)
{cout<<"int ctr"<<endl;}
myobject(std::string value)
{cout<<"string ctr"<<endl;}
};
int main()
{
list<boost::any> valueType;
std::string valStr("name");
valueType.push_back(valStr);
int num = 10;
valueType.push_back(num);
myobject* object = NULL;
for(list<boost::any>::iterator itr = valueType.begin();
itr != valueType.end();
++itr)
{
if((*itr).type() == typeid(std::string))
object = new myobject((boost::any_cast<std::string>(*itr)));
else if((*itr).type() == typeid(int))
object = new myobject((boost::any_cast<int>(*itr)));
}
return 0;
}

Calling a member function pointer stored in a std map

I'm storing a map in a class that has strings as keys and pointers to member functions as values. I'm having trouble calling the right function throw the function pointer.
Here is the code:
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Preprocessor;
typedef void (Preprocessor::*function)();
class Preprocessor
{
public:
Preprocessor();
~Preprocessor();
void processing(const string before_processing);
private:
void take_new_key();
map<string, function> srch_keys;
string after_processing;
};
Preprocessor::Preprocessor()
{
srch_keys.insert(pair<string, function>(string("#define"), &Preprocessor::take_new_key));
}
Preprocessor::~Preprocessor()
{
}
void Preprocessor::processing(const string before_processing)
{
map<string, function>::iterator result = srch_keys.find("#define");
if(result != srch_keys.end())
result->second;
}
void Preprocessor::take_new_key()
{
cout << "enters here";
}
int main()
{
Preprocessor pre;
pre.processing(string("...word #define other word"));
return 0;
}
In function Preprocessor::processing if the string is found in the map then, I call the proper function. The problem is that, in this code, Preprocessor::take_new_key is never called.
Where is the mistake ?
Thanks
The correct syntax is this:
(this->*(result->second))();
That is ugly. So lets try this:
auto mem = result->second; //C++11 only
(this->*mem)();
Use whichever makes you happy.
result->second does not call the function pointer. Try ((*this).*result->second)();