Как условно определить, какие функции вызваны во время компиляции?

статья This DDJ показывает способ использовать шаблонную специализацию, которая не требует, чтобы Вы использовали const_cast. Для такой простой функции это действительно не необходимо все же.

повышение:: any_cast (однажды, это больше не делает), использует const_cast от версии константы, называя версию неконстанты для предотвращения дублирования. Вы не можете наложить семантику константы на версию неконстанты хотя, таким образом, необходимо быть очень осторожны с этим.

В конце некоторое дублирование кода хорошо целый, эти два отрывка непосредственно друг на друге.

6
задан Brian Tompsett - 汤莱恩 27 November 2015 в 11:53
поделиться

9 ответов

Во время компиляции с макросом 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
1
ответ дан 8 December 2019 в 04:52
поделиться

Вам нужны указатели на функции, создайте массив указателей на функции и динамически индексируйте его.

Здесь ссылка об указателях функций.

11
ответ дан 8 December 2019 в 04:52
поделиться

Решение во время компиляции: этап предварительной сборки и включение директивы внутри этого цикла, например

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

Любая приличная система сборки позволит вам это сделать.

5
ответ дан 8 December 2019 в 04:52
поделиться

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 :-)

3
ответ дан 8 December 2019 в 04:52
поделиться

Что неправильно со старым условием if?

if (hasNetwork)
{
   network_process();
}
2
ответ дан 8 December 2019 в 04:52
поделиться

Вы можете сделать это с помощью массива указателей на функции. Обычно я стараюсь избегать указателей на функции, как чума, но это может быть вашим лучшим выбором.

В качестве альтернативы вы можете создать компонент функция процесса, которая принимает аргумент int, а затем имеет неприятный оператор switch ... но для того, чтобы это работало, вам нужно продолжать добавлять в функцию component_process.

В качестве альтернативы, вы можете сделать это на C ++, создать виртуальный класс Component, у которого есть только один метод "process" с кучей подклассов, и вы запускаете массив компонентов (фактически объекты подклассов) и вызываете метод процесса.

1
ответ дан 8 December 2019 в 04:52
поделиться

ваши компоненты должны быть массивом указателей на функции

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]();
1
ответ дан 8 December 2019 в 04:52
поделиться

Вот пример синтаксиса для выполнения этого во время выполнения с массивом указателей на функции:


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)();
}


0
ответ дан 8 December 2019 в 04:52
поделиться

Другая возможность: оставить цикл как есть, т.е.

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
0
ответ дан 8 December 2019 в 04:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: