У меня есть приложение на C++, где main() создает объект MyApp, а затем передает объект функции ReadConfig.Как вызвать функции C++ с различными сигнатурами с помощью указателя функции
ReadConfig открывает текстовый файл, анализирует его и вызывает соответствующие методы MyApp для его настройки.
class MyApp
{
private:
public:
void SetRate(uint16_t);
void EnableLogging(bool);
void SetAddress(uint32_t);
};
Я пытаюсь сделать его легко поддерживать ReadConfig таким образом, что, как новые общественные методы добавляются MyApp, это может быть столь же просто, как обновить таблицу. Я придумал следующее решение, но мне это не нравится. Его трудно поддерживать из-за того, что я должен поставить 0s в нужное место.
Ниже приведен пример того, что я смог выработать. Любые советы, чтобы сделать это лучше, будут оценены. Заметьте, что я работаю в embedded, поэтому компиляторы C++, которые мы используем, не поддерживают C++. 14 & нет никакого повышения. И я хотел бы избегать использования каких-либо библиотек STL, чтобы понять, как это сделать сама механика.
Вот что у меня есть:
enum ARGTYPE {TBOOL, TUINT16, TUINT32};
template<typename TOBJ, typename TARG>
struct TSetting
{
void (TOBJ::*FSet)(TARG);
};
template<typename obj>
struct SETTINGFN
{
const char *setting_name;
ARGTYPE Targ;
TSetting<obj,bool> HBool;
TSetting<obj,uint16_t> HUint16;
TSetting<obj,uint32_t> HUint32;
};
SETTINGFN<MyApp> MyAppSettings[] =
{
"logging" ,TBOOL, &MyApp::EnableLogging, 0,0,0
,"maxrate" ,TUINT16, 0,0,0,&MyApp::SetRate
,"address" ,TUINT32, 0, &MyApp::SetAddress, 0,0
};
unsigned int MyAppSettings_Count = sizeof(MyAppSettings)/sizeof(SETTINGFN<MyApp>);
Тогда как я прочитал конфигурационный файл и разобрать его, вызвать функцию для обработки вызова фактических функций MyApp через указатели на функции. Эта функция такова:
bool AppSetting(MyApp &E, TObjnode &node)
{
bool rval = false;
for(unsigned int i=0; i<MyAppSettings_Count && !rval; i++)
{
if(node.GetName() == MyAppSettings[i].setting_name)
{
rval = true;
switch(MyAppSettings[i].Targ)
{
case TBOOL:
(E.*MyAppSettings[i].HBool.FSet)(node.GetValue().AsBool());
break;
case TUINT16:
(E.*MyAppSettings[i].HUint16.FSet)(node.GetValue().Value());
break;
case TUINT32:
(E.*MyAppSettings[i].HUint32.FSet)(node.GetValue().Value());
break;
}
}
}
return(rval);
}
Рассмотренных передавая строку каждому сеттера, и позволяя им вызывать типоспецифический повторно используемый код синтаксического анализа? Тогда все сеттеры могут быть одного типа. Батут, который принимает строку, и вызывает как функцию синтаксического анализа, так и тип безопасности, может быть еще лучше. –
Итак, чтобы избежать необходимости добавлять вызов функции к вашей диспетчеру диспетчера конфигурации каждый раз при добавлении нового свойства/сеттера, вы хотите обновлять собственную структуру данных каждый раз при добавлении нового свойства/сеттера? Кажется, каждый из них ... –
Я думал об этом, но я надеялся избежать изменения текущих сигнатур функций или добавления новых – Eric