How to Call a Function by Its Name (Std::String) in C++

How to call a function by its name (std::string) in C++?

What you have described is called reflection and C++ doesn't support it. However you might come with some work-around, for example in this very concrete case you might use an std::map that would map names of functions (std::string objects) to function pointers, which in case of functions with the very same prototype could be easier than it might seem:

#include <iostream>
#include <map>

int add(int i, int j) { return i+j; }
int sub(int i, int j) { return i-j; }

typedef int (*FnPtr)(int, int);

int main() {
// initialization:
std::map<std::string, FnPtr> myMap;
myMap["add"] = add;
myMap["sub"] = sub;

// usage:
std::string s("add");
int res = myMap[s](2,3);
std::cout << res;
}

Note that myMap[s](2,3) retrieves the function pointer mapped to string s and invokes this function, passing 2 and 3 to it, making the output of this example to be 5

Calling a function using a string containing the function's name

This is not directly possible in C++. C++ is a compiled language, so the names of functions and variables are not present in the executable file - so there is no way for the code to associate your string with the name of a function.

You can get a similar effect by using function pointers, but in your case you are trying to use a member function as well, which complicates matters a little bit.

I will make a little example, but wanted to get an answer in before I spend 10 minutes to write code.

Edit: Here's some code to show what I mean:

#include <algorithm>
#include <string>
#include <iostream>
#include <functional>

class modify_field
{
public:
std::string modify(std::string str)
{
return str;
}

std::string reverse(std::string str)
{
std::reverse(str.begin(), str.end());
return str;
}
};

typedef std::function<std::string(modify_field&, std::string)> funcptr;

funcptr fetch_function(std::string select)
{
if (select == "forward")
return &modify_field::modify;
if (select == "reverse")
return &modify_field::reverse;
return 0;
}

int main()
{
modify_field mf;

std::string example = "CAT";

funcptr fptr = fetch_function("forward");
std::cout << "Normal: " << fptr(mf, example) << std::endl;

fptr = fetch_function("reverse");
std::cout << "Reverse: " << fptr(mf, example) << std::endl;
}

Of course, if you want to store the functions in a map<std::string, funcptr>, then that is entirely possible.

Making a function call to a function whose name is inside a string - C++

This would be the easiest solution, but I think your problem consists of several such calls?

std::string line = "The king's name is getKingName()";
if (line.find("getKingName()") != std::string::npos) {
King name = getKingName();
}

How to call a function from an object with a std::string

Several solutions are available to you. You basically want to parse user input to fill your Square class attribute.
One way is to use the std::stoi family of functions:

std::vector<string> values { "Roger", "2", "3.5" };

std::string name = values[0]; // No problem, two strings
int width = std::stoi(values[1]); // stoi = stringToInt
float happiness = std::stof(values[2]); // stof = stringToFloat

I'm not sure why you'd need the for loop, unless there is something I didn't understand in your question. I'll update my answer accordingly.

Update 1

After reading other answers, I would like to propose my solution to your problem. As stated several times in my comments, this is not an easy answer !

I needed such a class to write a generic test engine, and this is the code I used. It works really well with any type of function (except for routines with a return type of void -- a simple template specialization would solve it though)

# include <functional>
# include <tuple>

template<int ...>
struct seq
{
};

template<int N, int ...S>
struct gens : gens<N - 1, N - 1, S...>
{
};

template<int ...S>
struct gens<0, S...>
{
typedef seq<S...> type;
};

struct callable_base
{
virtual void operator()() = 0;

virtual ~callable_base()
{ }
};

class Task
{
private:
template<class RT, class Functor, class ...Args>
struct functor : public callable_base
{
functor(RT& result, Functor func, Args ...args)
: _ret(result)
{
_func = func;
_args = std::make_tuple(args...);
}

void operator()()
{
_ret = call(typename gens<sizeof...(Args)>::type());
}

template<int ...S>
RT call(seq<S...>)
{
return (_func(std::get<S>(_args)...));
}

private:
std::function<RT(Args...)> _func;
std::tuple<Args...> _args;
RT& _ret;
};

public:
Task()
{
_functor = nullptr;
}

template<class RT, class Functor, class ...Args>
Task(RT& result, Functor func, Args... args)
{
_functor = new functor<RT, Functor, Args...>(result, func, args...);
}

void operator()()
{
(*_functor)();
}

~Task()
{
delete _functor;
}

private:
callable_base *_functor;
};

The idea behind this code is to hide the function signature in the inner class Task::functor and get the return value in the first parameter passed to the Task(...) constructor. I'm giving this code first because I think it might help some people, but also because I think it is an elegant solution to your problem. Bear in mind that to understand most of the code, you need solid C++ knowledge. I'll detail the code in subsequent updates if needed.

Here's how you'd use it:

int main()
{
int retVal;
std::string newName;

std::map<std::string, Task *> tasks {
{"setName", new Task(retVal, &Square::setName, &newName)}
...
}

/* Modify the name however you want */

...
tasks["setname"]();
}

This whole class could be optimized, of course, primarily thanks to C++14 and move semantics, universal references and all, but I kept it simple ~
A major problem is that you have to use pointers if you don't know the values of the parameters at the time you fill the task map. I'm working on another version to simplify this aspect, but I wanted to show you that C++ is not designed to do what you ask simply. Maybe you come from a functional or JS world, in which this would be trivial x)

Update 2

I just wanted to point out that with C++14, you could omit the first 3 structures that are here to help me expand my tuple in an argument list using interger_sequence

Is there a way to dynamically call functions by their name in c++

No.
C++ doesn’t have this kind of reflection.

You can always create a structure which maps strings to function pointers, but you will have to initialize this structure yourself.

call a function by string

There is no way to directly call a function by string like you want in the standard C library. If it were C++, you could create a std::map of string to function pointer, but not in C. You'll probably have to resort to a series of strcmps if C++ is not an option.

/* These are your handler functions */
void user_fn() { printf("USER fn\n"); }
void pass_fn() { printf("PASS fn\n"); }

/* Stores a C string together with a function pointer */
typedef struct fn_table_entry {
char *name;
void (*fn)();
} fn_table_entry_t;

/* These are the functions to call for each command */
fn_table_entry_t fn_table[] = {{"USER", user_fn}, {"PASS", pass_fn}};

/* fn_lookup is a function that returns the pointer to the function for the given name.
Returns NULL if the function is not found or if the name is NULL. */
void (*fn_lookup(const char *fn_name))() {
int i;

if (!fn_name) {
return NULL;
}
for (i = 0; i < sizeof(fn_table)/sizeof(fn_table[0]); ++i) {
if (!strcmp(fn_name, fn_table[i].name)) {
return fn_table[i].fn;
}
}
return NULL;
}

int main() {
fn_lookup("USER")();
fn_lookup("PASS")();
}

C++ call function with string as parameter

You can use map to function pointers for this stuff

void func1(const char *args)
{
//....
}

void func2(const char *args)
{
//....
}

typedef void (*function) (const char *args);

//......

std::map<std::string, function> func_map;

func_map.insert(std::pair<std::string, function>("func1", func1));
func_map.insert(std::pair<std::string, function>("func2", func2));

func_map["func1"]("arg1 arg2 arg3"); // Here is the func1 call


Related Topics



Leave a reply



Submit