5

I have a class defined as

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

};

Is there any way to store this function name inside a string in main function and then call it. I tried this but it's not working.

int main()
{
modify_field  mf;
std::string str,str1,str2;
str = fetch_function_name(); //fetch_function_name() returns string modify
str2 = "check";
cout << str; //prints modify
str1 = str + "(" +str2 + ")";
mf.str1(); 
}

I know this is wrong. But I just want to know if there is any way to call a function name using variable.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
sajal
  • 91
  • 1
  • 1
  • 9
  • Just asking in interest: so cast from lvalue to functionpointer isn't practicable, is it? – dhein Aug 26 '13 at 10:40
  • Why don't you code an conversation method that for? – dhein Aug 26 '13 at 10:41
  • You can create a 'std::map' as your own jump table and call from that map lookup. – kfmfe04 Aug 26 '13 at 10:48
  • You might want to search SO for "[c++] reflection". – Christian.K Aug 26 '13 at 10:48
  • I'd suggest to try using functors with a factory that gives you the right one by string. Anyway, you will need to recompile your factory after adding more functors. But the most important - do you really need that? Maybe you can do what you want another way? You surely want to use reflection in c++, but do you really need that? – SpongeBobFan Aug 26 '13 at 11:19
  • use a mapping function. unless all your member functions have the same signature then u can use a hash map. – SwiftMango Aug 26 '13 at 17:16

6 Answers6

7

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.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • But names are present in dynamic libraries and can be looked up. – dtech Aug 26 '13 at 10:48
  • Reason for using member function is that we have two different classes where one is the main class and will not be changed at all. Whereas class modify_field will keep on changing as per requirement. – sajal Aug 26 '13 at 10:48
  • 2
    @Mats: strictly speaking, non-availability of name is not a consequence of the language being a compiled language, but rather of absence of runtime-accessible metadata. Other compiled languages (like C#) can access function names at runtime with introspection. The solutions involving a table mapping function to its name is exactly providing the metadata manually. – Vlad Aug 26 '13 at 11:30
  • @Vlad - this is true, Qt has already made some advances in this area. It comes at an overhead though, so that is why it is absent from C++, which is performance oriented. – dtech Aug 26 '13 at 12:23
  • 1
    @ddriver: well, if the metadata were a part of the language itself, the compiler might be able to add it separately so that one doesn't pay the price when not using the metadata (which seems to be quite aligned with C++'s approach). However it's not clear how to interoperate with inlining and other code transformations (I wonder how do the other languages deal with this problem). – Vlad Aug 26 '13 at 12:40
3

You have two choices:

1 - manually create a map with pointers to the functions you need and their identifiers as a string key so you can perform lookups, or..

2 - create a dynamic link library/shared object and use name lookup to get the pointer. Use extern "C" to prohibit identifier mangling. You may not be able to use certain C++ features and performance will be slightly worse, depending on your actual usage scenario.

dtech
  • 47,916
  • 17
  • 112
  • 190
2

It surely possible with C functions, but will be really tricky and unportable for C++ - because different OSes (and even different compilers on the same OS) uses different ABIs for C++, so real function names differ quite significantly from what you named them in your code.

If C functions is ok (e.g. you can declare them as extern "C"), you can use dlsym for POSIX OSes and GetProcAddress for windows. Of course, you'll need to add this functions into dynamic symbols table - something like '-rdynamic' flag for ld, or __declspec(dllexport) (hope that was right - haven't used if for a long time) on windows.

keltar
  • 17,711
  • 2
  • 37
  • 42
1

Maybe a pointer to this function is more adequate. It allows you to easily chose between functions to call:

#include<iostream>
using namespace std;

class modify_field
{
    public:
        std::string modify_1(std::string str)
        {
            return str;
        }
        std::string modify_2(std::string str)
        {
            return str + str;
        }
};

int main()
{
    string (modify_field::* fun_ptr) (string) = &modify_field::modify_1;
    modify_field m;
    cout << (m.*fun_ptr)("test") << endl;
    fun_ptr = &modify_field::modify_2;
    cout << (m.*fun_ptr)("test") << endl;
}
cpp
  • 3,743
  • 3
  • 24
  • 38
1

If the functions have same signature you can create a map of string to std::function objects. See more about std::function here: std::function

Asha
  • 11,002
  • 6
  • 44
  • 66
0

If you placed all the functions that you would like to lookup by name in a set of source files that you then generate a DLL with, you could use the dlopen() and dlsym() functions to find the entry point.

An example of how to do this can be found in the man pages of dlsym() on your machine, or you could refer to this link.

This only works well on functions that are unmangled (i.e. with C++ you may have some issues). You may either have to define these entry points as "extern C" to prevent mangling, or come up with some other mechanism to guess the mangled name for a C++ entry point. I have never done the latter so there are bound to be some nuances there that I'm oblivious to.

If you are using Windows (wasn't clear what OS you are on), you should lookup the documentation of GetProcAddress() which is available online here.

A good tutorial on the subject in general, and this one does talk about how to do all this with C++ can be found here.

amrith
  • 953
  • 6
  • 17