0

In my project I want to do something like following:

static void test0(void)
{
    printf("%s [%d]\n", __func__, __LINE__);
}

static void test0(int a)
{
    printf("%s [%d] %d\n", __func__, __LINE__, a);
}

static std::map<std::string, void*> initializeAddressMap()
{
    std::map<std::string, void*> addressmap;
    addressmap["test0"] = (void*) &test0;    // ERROR HERE <------
    return addressmap;
}

Basically, the third function returns a mapping of string to function address. However, at this point, I get an error address of overloaded function with no contextual type information, which also makes sense, since I have overloaded the test0 function, and compiler at this point doesn't know the address of which function to take. Is there any way I could address this problem, other than calling my functions different names?

KelvinS
  • 2,870
  • 8
  • 34
  • 67
Aksim Elnik
  • 425
  • 6
  • 27
  • @LogicStuff quite logic stuff... – Aksim Elnik Jul 17 '17 at 14:13
  • 1
    Which `test0` function's address do you want? – François Andrieux Jul 17 '17 at 14:14
  • @FrançoisAndrieux well an example for each of them would be nice, but lets for example take the `test0(int a)` – Aksim Elnik Jul 17 '17 at 14:15
  • 3
    Possible duplicate of [How do I specify a pointer to an overloaded function?](https://stackoverflow.com/questions/2942426/how-do-i-specify-a-pointer-to-an-overloaded-function) – François Andrieux Jul 17 '17 at 14:17
  • @AksimElnik so what "contextual type information" are you giving it? I only see a map with a string key, and void pointer for values. https://stackoverflow.com/questions/2136998/using-a-stl-map-of-function-pointers – AresCaelum Jul 17 '17 at 14:26
  • @Eddge I assume it needs parameters of the overloaded function , that i could provide , but i do not know the right way of doing that.... – Aksim Elnik Jul 17 '17 at 14:39
  • @AksimElnik the link I provided shows how to do that, and answers below give an example how to do that as well. – AresCaelum Jul 17 '17 at 14:40
  • Trying to put both types of pointers into a map will cause you to lose information. You won't know the actual type of the pointer being stored (is it `test0(void)` or `test0(int)`? You would have to also track that information for each pointer. Perhaps you would be interested in learning about [`std::function`](http://en.cppreference.com/w/cpp/utility/functional/function) and [lambda expressions](http://en.cppreference.com/w/cpp/language/lambda). – François Andrieux Jul 17 '17 at 14:51

2 Answers2

3

You should define pointer type when getting function address:

#include <iostream>

static void test(void)
{
    printf("%s [%d]\n", __func__, __LINE__);
}

static void test(int a)
{
    printf("%s [%d] %d\n", __func__, __LINE__, a);
}

int main()
{
    using t_pf1 = void (*)(void);
    using t_pf2 = void (*)(int);
    ::std::cout << (uintptr_t) t_pf1{&test} << "\n"
      << (uintptr_t) t_pf2{&test} << ::std::endl;
    return 0;
}

working code online

user7860670
  • 35,849
  • 4
  • 58
  • 84
  • @AksimElnik Well, you can cast them to void * and squeeze into the map like you already do. – user7860670 Jul 17 '17 at 14:42
  • what does the `(*)` do? What if i have many more functions whose addresses i want to store in the map? – Aksim Elnik Jul 17 '17 at 14:45
  • @AksimElnik `(*)` is a part of function pointer declaration. If you have many more functions with the same name you'll need to declare many more function pointer types. Also you can utilize [Straight Declarations library](https://github.com/guaranteed-to-be-unique/Straight-Declarations) that makes it possible to write function pointer declarations in more intuitive manner, like this `ptr< void (int) >`. – user7860670 Jul 17 '17 at 14:51
  • @VTT and to cast the function pointers to void* , i would need to use the `reinterpret_cast` ? which seems not to work though... – Aksim Elnik Jul 17 '17 at 14:59
  • @AksimElnik Obviously you can't since type information is lost after you cast function pointer to void *. To call a function you'll need to cast `void *` back to correct function pointer type. – user7860670 Jul 17 '17 at 15:02
  • @VTT hmm , so then it is not possible to store all these function pointers in a map? – Aksim Elnik Jul 17 '17 at 15:05
  • @AksimElnik It is totally possible, you just need to keep information about actual type of each stored pointer to be able to correctly call a function using it. – user7860670 Jul 17 '17 at 15:12
  • @VTT that sounds possible for me, how exactly would i store the pointers in a map? I would be very thankful if you could provide me an example of that. – Aksim Elnik Jul 17 '17 at 15:22
  • @AksimElnik You should can store them just like you did before, you just need to obtain function address at matching pointer constructor. `using t_pf = void (*)(void); addressmap["test0"] = reinterpret_cast< void * >(t_pf{&test});` – user7860670 Jul 17 '17 at 15:29
1

The easiest solution is to store the pointer to the overloaded function in a pointer, first:

#include <cstdio>

static void test0(void)
{
    printf("%s [%d]\n", __func__, __LINE__);
}

static void test0(int a)
{
    printf("%s [%d] %d\n", __func__, __LINE__, a);
}

int main(void) {
    void (*select1)(void) = test0;  // will match void(void)
    void (*select2)(int) = test0;   // will match void(int)

    select1();
    select2(42);

    return 0;
}

$ ./a.out
test0 [5]
test0 [10] 42

If you want to call the stored void*, then you have to make it a function pointer again. You can do that by e.g. reinterpret_cast<void(*)(int)>(p).

Kijewski
  • 25,517
  • 12
  • 101
  • 143
  • I really need to put the addresses into that `std::map addressmap` ... How would that be possible? Sorry if i am asking noob questions... – Aksim Elnik Jul 17 '17 at 14:33
  • You can `reinterpret_cast` a function pointer to a `void*`, but most likely this is not what you want to do. – Kijewski Jul 17 '17 at 14:42
  • `addressmap["test0"]=reinterpret_cast(select1);` kind of works, however when i extract the void* element from the map, it looks like i cannot call the function with it... – Aksim Elnik Jul 17 '17 at 15:01
  • Please see my added paragraph. – Kijewski Jul 17 '17 at 15:22