Препроцессор Повышения (который работает на C, а также C++, даже при том, что Повышение в целом является библиотекой C++) библиотека может помочь с этим видом задачи. Вместо того, чтобы использовать #ifdef в рамках макроса (который не разрешен), это помогает Вам включать файл многократно с различными макросами, определенными каждый раз, так, чтобы файл мог использовать #ifdef.
следующий код, если сохранено к max.c, должен сделать то, что Вы хотите для каждого из слов, перечисленных в МАКСАХ #define наверху файла. Однако это не будет работать, если какое-либо из значений _MAX будет плавающей точкой, так как препроцессор не может обработать плавающую точку.
(Процессор повышения является удобным инструментом, но это не точно просто; можно решить, является ли этот подход улучшением по сравнению с копией-и-вставкой.)
#define MAXES (SHRT)(INT)(LONG)(PATH)(DOESNT_EXIST)
#if !BOOST_PP_IS_ITERATING
/* This portion of the file (from here to #else) is the "main" file */
#include <values.h>
#include <stdio.h>
#include <boost/preprocessor.hpp>
/* Define a function print_maxes that iterates over the bottom portion of this
* file for each word in MAXES */
#define BOOST_PP_FILENAME_1 "max.c"
#define BOOST_PP_ITERATION_LIMITS (0,BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(MAXES)))
void print_maxes(void) {
#include BOOST_PP_ITERATE()
}
int main(int argc, char *argv[])
{
print_maxes();
}
#else
/* This portion of the file is evaluated multiple times, with
* BOOST_PP_ITERATION() resolving to a different number every time */
/* Use BOOST_PP_ITERATION() to look up the current word in MAXES */
#define CURRENT BOOST_PP_SEQ_ELEM(BOOST_PP_ITERATION(), MAXES)
#define CURRENT_MAX BOOST_PP_CAT(CURRENT, _MAX)
#if CURRENT_MAX
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is %lld\n", (long long) CURRENT_MAX);
#else
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is undefined\n");
#endif
#undef CURRENT
#undef CURRENT_MAX
#endif
Я попробовал это прежде. Проблема состоит в том, что #
уже резервируется к stringize макро-параметр. Это не анализируется, поскольку маркер препроцессора как тот в #
определяет.
Единственное решение, которое я имею, обманывает - производят список типов, которые имеют _XXX_MAX, поскольку ряд определяет, и затем используйте это. Я не знаю, как произвести список автоматизированным способом в препроцессоре, таким образом, я не пробую. Предположение - то, что список не является слишком длинным и не будет вестись слишком интенсивно.
#define PRINT_MAX(type) printf("%lld\n", _TYPE##_MAX);
#define HAVE_MAX(type) _TYPE##_MAX // not sure if this works
/* a repetitious block of code that I cannot factor out - this is the cheat */
#ifdef HAVE_MAX(INT)
#define PRINT_INT_MAX PRINT_MAX(INT)
#endif
#ifdef HAVE_MAX(LONG)
#define PRINT_LONG_MAX PRINT_MAX(LONG)
#endif
/* end of cheat */
#define print_max(type) PRINT_##TYPE##_MAX
Я не думаю, что это - случай ## оператора, не позволяемого в #ifdef. Я попробовал это:
#define _print_max(TYPE) \
#ifdef TYPE \
printf("%lld\n", _TYPE); \
#endif
#define print_max(TYPE) _print_max(MAX##_TYPE)
void main()
{
print_max(INT)
}
и это все еще не работало (этому не нравился ТИП #ifdef). Проблема состоит в том, что #ifdef только примет #defined символы, не #define аргументы. Те - две разных вещи.
В отличие от шаблонов, препроцессор не полон Тьюрингом . #ifdef
внутренняя часть макрос не возможен. Ваше единственное решение состоит в том, чтобы удостовериться, что Вы только звоните print_max
на типах, который имеет соответствие _MAX
определенный, например, INT_MAX
. Компилятор, конечно, скажет Вам, когда они не будут.
Нет простого способа сделать это. Самое близкое, что вы можете сделать, - это #define большое количество макросов IFDEF, таких как:
#undef IFDEF_INT_MAX
#ifdef INT_MAX
#define IFDEF_INT_MAX(X) X
#else
#define IFDEF_INT_MAX(X)
#endif
#undef IFDEF_BLAH_MAX
#ifdef BLAH_MAX
#define IFDEF_BLAH_MAX(X) X
#else
#define IFDEF_BLAH_MAX(X)
#endif
:
, так как вам нужно много из них (и они могут быть полезны в нескольких местах), это дает много Имеет смысл поместить все это в отдельный файл заголовка ifdefs.h, который вы можете включить, когда вам это понадобится. Вы даже можете написать сценарий, который регенерирует ifdef.h из список «представляющих интерес макросов»
Затем ваш код станет
#include "ifdefs.h"
#define print_max(TYPE) \
IFDEF_##TYPE##_MAX( printf("%lld\n", TYPE##_MAX); )
print_max(INT);
print_max(BLAH);