0

I am extracting a string from a .txt file and saving it in a variable:

std::string line = "The king's name is getKingName()";

Lets assume that getKingName() is a function that returns a King class' name data member.

How can I make a call to getKingName() when the string variable looks like that?

Pete
  • 61
  • 1
  • 7
  • 2
    Does this answer your question? [Is there C/C++ equivalent of eval("function(arg1, arg2)")?](https://stackoverflow.com/questions/11078267/is-there-c-c-equivalent-of-evalfunctionarg1-arg2) – GoodDeeds Jan 24 '20 at 12:29
  • I have seen those answers before and I couldn't really figure out if I could apply them to my case. Could you provide example code using the example string above? – Pete Jan 24 '20 at 12:36
  • 2
    You need some way to parse the function name out of the string (depends on your input formatting). Then, you can create a map that maps the function name string to the function, and call the map with the parsed function name. – GoodDeeds Jan 24 '20 at 12:38
  • 1
    First, which is the problem? Finding the name of the method or invoking the method once you already found it? And what have you tried doing/what is the specific problem you found? – SJuan76 Jan 24 '20 at 12:44

3 Answers3

2

As far as I know, C++ does not provide such kind of functionality to interpolate functions call inside a string. All you can do implement your own logic to do that. Like,

1) define all the valid methods like this,

string getKingName(){
 return "Some name";
}

string otherMethods(){
  return "other values";
}

2) One helper method for mapping of function call

string whomToCall(string methodName){
    switch(methodName){
       case "getKingName()": 
          return getKingName();
          break;
       case "otherMethods()": 
          return otherMethods();
          break;
       default: 
          return "No such method exist";       
    }
}

3) break the line in tokens(words), read one by one and check for following condition also if token starts with any alphabetical character and ends with "()" substring

    istringstream ss(line);
    do { 
        string token; 
        ss >> token; 

        if(isMethod(token))
           cout << whomToCall(token) << " ";
         else
           cout << token<< " "; 
    } while (ss); 

4) isMethod() to check if token's value can be a valid method name

bool isMethod(string token){
   int n= token.length();
   return isalpha(token[0]) && token[n-2]=='(' && token[n-1] == ')' ;
}
1

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();
}
RoQuOTriX
  • 2,871
  • 14
  • 25
  • The problem is that the function call could be pretty much anywhere in the string - beginning/middle/end of string. – Pete Jan 24 '20 at 12:38
  • Then use the `find()` function. I will edit my code – RoQuOTriX Jan 24 '20 at 12:39
  • or use a regex like `[A-Za-z]+\(\)` – Marc Stroebel Jan 24 '20 at 12:49
  • @MarcStröbel I don't like the usage of regular expressions, for such an "easy" task. Regular expressions often lead to unwanted "features" – RoQuOTriX Jan 24 '20 at 12:51
  • Also a better "modern" style would be to use std::map. Use this implace of a swtch statement. Consider std::hash_map for speed. Std::function lets you use lambda functions, which can be convenient. – Tiger4Hire Jan 24 '20 at 13:06
  • @Tiger4Hire As i wrote, this would be only sufficient, if there exist up to e.g. 3 calls. If it would be more, than a solution like yours is better. Or if you know, that there are going to be much more calls later. but as long we don't no that and we "only" have one function, this would be a very easy understandable solution – RoQuOTriX Jan 24 '20 at 13:20
0

Amended

This answer is a little off subject. I will leave it up, because others might find it relevant, but I agree with other answers, a simple map->function will work better for your case.

This is not supported by C++. C++ is not an interpreted language. If you you want to do things like this, why not use an interpreted language, which do these sorts of things by default. Languages like lua are designed to call C/C++ functions with an interpreted language, with a small overhead.

However, if you really need to do this, it is possible, depending on your operating system. For example,

  1. On windows start with dbghelp. You will need to build a pdb, (e.g. build with symbols).
  2. On linux, you will also need to build symbols (-g), and use something like dlsym see here for a discussion.

That said, there are lots of gotchas doing it this way. Optimization can get in the way (best to disable them). Also best to avoid dynamic linking (prefer static). You will also need to cope with C++ name mangling (the name of the function is not the name of your function in C++). see https://blog.oakbits.com/how-to-mangle-and-demangle-a-c-method-name.html.

Tiger4Hire
  • 1,065
  • 5
  • 11
  • I support your answer, but I think OP has a fixed size of possibilities. He does not need dynamically call every function hin his program – RoQuOTriX Jan 24 '20 at 12:49
  • I agree, on reflection this answer is too complex. I'm wondering how to edit it to make this clearer. – Tiger4Hire Jan 24 '20 at 12:52