Есть ли способ получить искаженное имя функции typeinfo на основе подписи, используя RTTI?

Я хочу использовать строки типа RTTI и искаженной функции (указателя).

Прежде чем вы классифицируете это как проблему XY, я знаю, что есть лучшие варианты привязки функций с использованием полиморфизма и т. д.

Это чисто академический вопрос, как правильно использовать typeid() с указателями функций, которые должны отличаться своими юридически перегруженными сигнатурами.

Если я использую следующий код, похоже, я могу получить уникальные значения typeinfo::name() для различных пространств имен. /типы:

#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;
}

Результат:

PFviE
PFviE
M3barFviE
PFviE

Совершенно то, что я ожидал (я предполагаю, что i в искаженном имени относится к сигнатуре параметра).


Теперь я хочу иметь что-то вроде этого (что является совершенно законной перегрузкой функций):

#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;
}

и, конечно же, компилятор жалуется на двусмысленность:

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

Каков правильный синтаксис для указания конкретной перегрузки функции с помощью typeid() (если есть)?

Как я могу предоставить информацию о контекстном типе, которая требуется из сообщения об ошибке?


Я пришел из здесь в режиме глубокого размышления.


person user0042    schedule 10.11.2017    source источник


Ответы (1)


Чтобы выбрать конкретную функцию из набора перегруженных функций, вы можете использовать нотацию приведения:

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;

В частности, с typeid, если у вас уже есть записанный тип, вы можете пропустить фактическое имя функции.

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

короче и делает свою работу так же хорошо.

person n. 1.8e9-where's-my-share m.    schedule 10.11.2017