2012-05-21 4 views
1

Я программирую в очень статической среде и хотел бы как можно лучше обобщить проблему/код, сделать его чистым и избежать любого кода шаблона. Это мое дело; Я разрабатываю систему модификации, которая находится между программой и расширениями , где расширения будут перенаправлены на вызовы API. Когда моя модификация загружается программой, я получаю указатель на таблицу, состоящую целиком из указателей функций.Обобщение шаблона C++

struct APITable 
{ 
void (*MouseClick)(int, int); 
void (*MouseLeave)(bool); 
int (*MouseRet)(float, int); 
// And about a 200 more 
// ...... 
}; 

В этой функции я установил обратный вызов функции/указатели, чтобы указать на мой собственный (т.е. apiTable->MouseClick = &MyMouseClick;). Я пытаюсь расширить эту структуру (поскольку она позволяет только одну модификацию за раз) поддерживать несколько плагинов. Это делается путем загрузки дополнительных плагинов (в виде библиотек), а затем пересылает все обратные вызовы (например, MouseClick) загруженным плагинам. Это пример;

void MyMouseClick(int x, int y) 
{ 
bool blockOriginal = false; 

// Iterate over all plugins 
if(plugin_function_is_defined_pre) 
    blockOriginal = call_plugin_callback_pre(x, y); 

if(!blockOriginal) 
    EngineMouseClick(x, y); // This is the programs "engine" function, which I have to call if I want normal execution flow 

// Iterate over all plugins 
if(plugin_function_is_defined_post) 
    call_plugin_callback_post(x, y); 
} 

Это очень упрощенная процедура, но я думаю, что она рассказывает все, что нужно сказать. Поскольку у меня более 200 функций, я бы не копировал и не вставлял весь этот шаблонный код. Обычной процедурой, вероятно, будет #define, один для функций void и один для функций с возвращаемым значением. Хотя это и работает, я определенно предпочел бы другое решение (что может быть невозможно, поскольку C++ является статически типизированным языком).

Дело в том, Я хочу обобщить эту процедуру чистым и эффективным способом, избегая любых шаблонов. Стоит упомянуть, что функции могут переопределить исходное значение возвращаемых функций, в обратных вызовах, которые не объявлены как void.

Так, чтобы лишить его до костей: Program->MyExtension->Plugins&Engine

ПРИМЕЧАНИЕ: Я не хотите использовать любой язык, но C++, и будет использовать C++ 11 функций, если это необходимо!

EDIT: В случае заинтересованности, это как моя модификация загружается программа:

extern "C" ModLoad(APITable * apiTable) 
{ 
apiTable->MouseClick = &MyMouseClick; 
apiTable->MouseLeave = &MyMouseLeave; 
// And so on 
// ... 
} 
+6

«указатель на таблицу, состоящую целиком из указателей на функции» - это немного похоже на то, что вы пытаетесь переопределить C++ в C++ ... –

+0

Также неясно, как ваш 1-й фрагмент кода относится ко второму фрагменту кода. –

+0

@ Oli - что-то вроде Spring или другого каркаса IoC на C++, возможно –

ответ

3

, который не может быть возможным, так как C++ является статически типизированного языка

Если только C++ имел статически типизированный способ писать общий код, который может быть настроен для разных параметров, возможно, какой-то шаблонный объект? ;-)

N.B. Я понятия не имею, как вы собираетесь обрабатывать возвращаемые значения или то, что должно делать blockOriginal, или обратные вызовы, так что это всего лишь эскиз.

template<typename Res, typename... Args> 
    Res call_plugin_func(Enum funcID, Res (*origFunc)(Args...), Args... args) 
    { 
    Res res = Res(); 
    bool blockOriginal = false; 

    // Iterate over all plugins, looking for defs of funcID 
    if(plugin_function_is_defined_pre) 
     blockOriginal = call_plugin_callback_pre(args...); 

    if(!blockOriginal) 
     res = origFunc(args...); 

    // Iterate over all plugins 
    if(plugin_function_is_defined_post) 
     call_plugin_callback_post(args...); 

    return res; 
    } 

template<typename... Args> 
    void call_plugin_func(Enum funcID, void (*origFunc)(Args...), Args... args) 
    { 
    bool blockOriginal = false; 

    // Iterate over all plugins, looking for defs of funcID 
    if(plugin_function_is_defined_pre) 
     blockOriginal = call_plugin_callback_pre(args...); 

    if(!blockOriginal) 
     origFunc(args...); 

    // Iterate over all plugins 
    if(plugin_function_is_defined_post) 
     call_plugin_callback_post(args...); 
    } 

void MyMouseClick(int x, int y) 
{ 
    call_plugin_func(ID_MyMouseClick, &EngineMouseClick, x, y); 
} 

(два шаблона функции необходимы, потому что один возвращение аннулируются имеет другое тело, оно не может объявить res быть типа void.)

+0

Для функции void вполне допустимо возвращать выражение типа 'void', как это имеет место для другой функции, возвращающей void. –

+0

Да, но OP сказал: «Стоит упомянуть, что функции могут переопределять возвращаемое значение исходных функций, в обратных вызовах, которые не объявлены как void». так что, возможно, тело шаблона функции должно выполнить 'Res value = plugin (args ...); ... return Res ;, но это было бы невозможно, если Res недействительна, поэтому вам может понадобиться другой шаблон функции. Отредактировано, чтобы это отразить. –

+3

В C++ 11, 'Res res = Res();' написано 'Res res {};'. – ildjarn

Смежные вопросы