статья This DDJ показывает способ использовать шаблонную специализацию, которая не требует, чтобы Вы использовали const_cast. Для такой простой функции это действительно не необходимо все же.
повышение:: any_cast (однажды, это больше не делает), использует const_cast от версии константы, называя версию неконстанты для предотвращения дублирования. Вы не можете наложить семантику константы на версию неконстанты хотя, таким образом, необходимо быть очень осторожны с этим.
В конце некоторое дублирование кода хорошо целый, эти два отрывка непосредственно друг на друге.
Во время компиляции с макросом X:
component.x - это файл, содержащий:
COMPONENT( graphic , "3D graphics rendering" )
COMPONENT( network , "Network" )
COMPONENT( other , "usefull stuff" )
#undef COMPONENT
Используйте его с:
#define COMPONENT( what , description ) what ## _process();
while (1)
{
#include "components.x"
}
И в другом месте, например:
std::cout << "We use :\n" ;
#define COMPONENT( what , description )\
std::cout << #what << " : " << description << "\n" ;
#include "components.x"
и с этим вы можете поместить определения HAS_ в одном месте в component.x:
#ifdef HAS_GRAPHIC
COMPONENT( graphic , "3D graphics rendering" )
#endif
#ifdef HAS_NETWORK
COMPONENT( network , "Network" )
#endif
#ifdef HAS_OTHER
COMPONENT( other , "usefull stuff" )
#endif
#undef COMPONENT
Вам нужны указатели на функции, создайте массив указателей на функции и динамически индексируйте его.
Здесь ссылка об указателях функций.
Решение во время компиляции: этап предварительной сборки и включение директивы внутри этого цикла, например
while (1) {
#include "components.generated.c"
}
Базовый сценарий для создания этого файла может выглядеть так (Python):
components = ('input', 'networking', 'graphics')
# this could also be e.g. a glob on a directory or a config file
with open('components.generated.c', 'w') as fp:
for component in components:
print >>fp, '%s_process();' % component
Любая приличная система сборки позволит вам это сделать.
Function pointers are great!
typedef void (*process_fun)(void);
process_fun processes[] =
{ input_process, network_process, graphics_process };
#define NELEMS(A) (sizeof(A) / sizeof((A)[0]))
while (1) {
for (int i = 0; i < NELEMS(processes); i++)
processes[i]();
}
The NELEMS
macro, which I learned from Dave Hanson, is also one of my favorites.
P.S. Avoid #ifdef
at all costs :-)
Что неправильно со старым условием if?
if (hasNetwork)
{
network_process();
}
Вы можете сделать это с помощью массива указателей на функции. Обычно я стараюсь избегать указателей на функции, как чума, но это может быть вашим лучшим выбором.
В качестве альтернативы вы можете создать компонент функция процесса, которая принимает аргумент int, а затем имеет неприятный оператор switch ... но для того, чтобы это работало, вам нужно продолжать добавлять в функцию component_process.
В качестве альтернативы, вы можете сделать это на C ++, создать виртуальный класс Component, у которого есть только один метод "process" с кучей подклассов, и вы запускаете массив компонентов (фактически объекты подклассов) и вызываете метод процесса.
ваши компоненты должны быть массивом указателей на функции
enum components
{
input,
network,
graphics,
num_components
}
void process_audio()
{
}
void process_network()
{
}
void process_graphics()
{
}
void (*process_component[num_components])();
process_component[0] = &process_audio;
process_component[1] = &process_network
process_component[2] = &process_graphics;
for (int i = 0; i < num_components; i++)
process_component[i]();
Вот пример синтаксиса для выполнения этого во время выполнения с массивом указателей на функции:
void f( void ) { puts( "f" ); } void g( void ) { puts( "g" ); } void h( void ) { puts( "h" ); } void (*array[])(void) = { f, h, 0 }; int main(void) { void (**t)(void); for( t = array; *t; t++ ) (*t)(); }
Другая возможность: оставить цикл как есть, т.е.
while (1) {
input_process();
network_process();
graphics_process();
}
и добавить следующие директивы препроцессора в заголовок файла:
#ifndef HAS_NETWORK
#define network_process() ((void)0)
#endif
#ifndef HAS_GRAPHICS
#define graphics_process() ((void)0)
#endif