c++rttitypeidtypeinfo

Is there a way to get a signature based typeinfo mangled function name using RTTI?


I want to use RTTI and mangled function (pointer) type strings.

Before you categorize this as an XY problem, I'm aware that there are better options to bind functions using polymorphism etc.

This is a purely academical question how to use typeid() properly with function pointers that should differ by their legally overloaded signatures.

If I use the following code, it seems I can retrieve unique typeinfo::name() values for various namespaces/types:

#include <iostream>
#include <typeinfo>
#include <string>

void foo(int) {
}

namespace woozle {
    void goozle(int) {}
}

struct bar {
    void baz(int) {}
    static void boo(int) {}
};

int main() {
    std::cout << typeid(&foo).name() << std::endl;
    std::cout << typeid(&woozle::goozle).name() << std::endl;
    std::cout << typeid(&bar::baz).name() << std::endl;
    std::cout << typeid(&bar::boo).name() << std::endl;
}

The output is:

PFviE
PFviE
M3barFviE
PFviE

Perfectly what I expected (I assume the i in the mangled name refers to the parameter signature).


Now I want to have something like this (which is perfectly legal function overloading):

#include <iostream>
#include <typeinfo>
#include <string>

void foo(int) {
}

void foo(std::string) {
}

namespace woozle {
    void goozle(int) {}
    void goozle(std::string) {}
}

struct bar {
    void baz(int) {}
    static void boo(int) {}
    void baz(std::string) {}
    static void boo(std::string) {}
};

int main() {
    std::cout << typeid(&foo).name() << std::endl;
    std::cout << typeid(&woozle::goozle).name() << std::endl;
    std::cout << typeid(&bar::baz).name() << std::endl;
    std::cout << typeid(&bar::boo).name() << std::endl;
}

and of course the compiler complains about ambiguity:

main.cpp: In function 'int main()':
main.cpp:24:25: error: address of overloaded function with no contextual type information
     std::cout << typeid(&foo).name() << std::endl;
                         ^~~~
main.cpp:25:25: error: address of overloaded function with no contextual type information
     std::cout << typeid(&woozle::goozle).name() << std::endl;
                         ^~~~~~~
main.cpp:26:25: error: address of overloaded function with no contextual type information
     std::cout << typeid(&bar::baz).name() << std::endl;
                         ^~~~
main.cpp:27:25: error: address of overloaded function with no contextual type information
     std::cout << typeid(&bar::boo).name() << std::endl;
                         ^~~~

TL;DR

What is the proper syntax to specify a specific function overload with typeid() (if there is any)?

How can I provide the "contextual type information" that is demanded from the error message?


I'm coming from here in deep thinking mode.


Solution

  • To select a specific function from a set of overloaded functions you can use use the cast notation:

    std::cout << typeid(static_cast<void (*)(int)>(foo)).name() << std::endl;
    std::cout << typeid(static_cast<void (*)(std::string)>(foo)).name() << std::endl;
    std::cout << typeid(static_cast<void (bar::*)(int)>(&bar::baz)).name() << std::endl;
    std::cout << typeid(static_cast<void (bar::*)(std::string)>(&bar::baz)).name() << std::endl;
    

    Specifically with typeid though, if you have the type already written down, you can skip the actual function name.

    std::cout << typeid(void (*)(int)).name() << std::endl;
    

    is shorter and does the job just as well.