#c
#c
Вопрос:
Я хотел бы сохранить различные функции-члены в таблице, аналогичной библиотеке Sol2.
Предоставляются функции-члены разных классов с разными возвращаемыми значениями и разными параметрами. Возможно ли сохранить эти функции-члены в таблице в C и выполнить их позже? Я подозреваю, что библиотека Sol2 (привязка c lua) хранит указатели на функции в std::tuple. Но я не понял, как тогда выполнять функции.
Вот пример кода для лучшего понимания вопроса:
// various classes with different member functions
struct classA
{
void function_a() {}
bool function_b( int nValue1 ) {}
int function_c( int nValue1, int nValue2 ) {}
};
struct classB
{
int function_a() {}
void function_b( int nValue1 ) {}
bool function_c( int nValue1, int nValue2 ) {}
};
struct FunctionTable
{
// function to store a memberfunction with a object instance
template<class T, class ... Args>
void addFunction( std::string strFunctionName, T * t, Args ... args )
{
// how to store the function pointer?
}
// function for returning the stored function pointer
? ? ? get(std::string strFunctionName)
{
return m_mapFunctions[strFunctionName];
}
// how to store the pointers in a container, e. g. std::map?
std::map<std::string, ? ? ? > m_mapFunctions;
};
void main2()
{
classA a;
classB b;
FunctionTable functionTable;
// store different member functions in to the function table with a name as index
functionTable.addFunction( "classA_function_a", amp;a, amp;classA::function_a );
functionTable.addFunction( "classA_function_b", amp;a, amp;classA::function_b );
functionTable.addFunction( "classA_function_c", amp;a, amp;classA::function_c );
functionTable.addFunction("classB_function_a", amp;b, amp;classB::function_a);
functionTable.addFunction("classB_function_b", amp;b, amp;classB::function_b);
functionTable.addFunction("classB_function_c", amp;b, amp;classB::function_c);
// Example calls
auto functionA = functionTable.get("classA_function_a");
functionA();
auto functionB = functionTable.get("classA_function_b");
bool bReturnValue = functionB(99);
auto functionC = functionTable.get("classA_function_c");
int nReturnValue = functionC(23, 24);
}
У кого-нибудь есть идея или подсказка, как это можно реализовать?
Комментарии:
1. Исходя из того, какая информация о типе доступна во всех ваших примерах вызовов, вам нужно ввести-стереть все, затем вывести, какой тип функции предположительно был с сайта вызова. Однако это кажется мне крайне небезопасным.
2. Не могли бы вы предоставить
get
аргументы и возвращаемый тип, которые, как вы ожидаете, должна иметь возвращаемая функция? Кажется, вы должны знать это в любом случае, основываясь на том, как вы используете результат. Редактировать: Из того, что я вижу, вы могли бы также просто сохранитьstd::any
и привести обратно к ожидаемому типу функции.
Ответ №1:
C — это статически типизированный язык. Карты однородны: все элементы карты имеют точно такой же тип.
Тип указателя на функцию одного типа отличается от типа указателя на функцию другого типа. Тип функции определяется ее типами аргументов и возвращаемых значений. Таким образом, невозможно хранить указатели на функции с разными списками аргументов или возвращаемыми типами в одной карте.
Однако существуют методы «стирания типов», которые позволяют имитировать динамическую типизацию. Стандартная библиотека C поставляется с двумя разнородными оболочками: std::variant
и std::any
. Вариант — это реализация помеченного объединения. Его можно использовать для хранения объекта из заранее определенного списка типов. any
является типобезопасной оболочкой для void*
. Он может хранить объект любого типа. Итак, карта variant or any
может быть тем, что вы ищете.
Однако это всего лишь инструменты низкого уровня, и для более функциональной разнородной обработки существуют библиотеки, такие как Boost.Hana.
Комментарии:
1. @SamerTufail в последнее время было много похожих (но не совсем одинаковых) вопросов 🙂 Я предполагаю, что есть несколько университетских курсов с аналогичными заданиями.