Хранение и доступ к различным функциям-членам в таблице

#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 в последнее время было много похожих (но не совсем одинаковых) вопросов 🙂 Я предполагаю, что есть несколько университетских курсов с аналогичными заданиями.