I would like to do the equivalent of the following:
我想做如下的对等工作:
#define print_max(TYPE) \
# ifdef TYPE##_MAX \
printf("%lld\n", TYPE##_MAX); \
# endif
print_max(INT);
Now the #ifdef
or any nested preprocessor directive is not allowed as far as I can see in a function macro. Any ideas?
现在,#ifdef或任何嵌套的预处理器指令都不允许在函数宏中看到。什么好主意吗?
Update: So it seems like this is not possible. Even a hack to check at runtime seems unachievable. So I think I'll go with something like:
更新:看来这是不可能的。即使是在运行时检查也不可能实现。所以我想我应该这样说:
#ifndef BLAH_MAX
# define BLAH_MAX 0
#endif
# etc... for each type I'm interested in
#define print_max(TYPE) \
if (TYPE##_MAX) \
printf("%lld\n", TYPE##_MAX);
print_max(INT);
print_max(BLAH);
6 个解决方案
#1
11
The Boost Preprocessor (which works for C as well as C++, even though Boost as a whole is a C++ library) library can help with this kind of task. Instead of using an #ifdef within a macro (which isn't permitted), it helps you include a file multiple times, with different macros defined each time, so that the file can use #ifdef.
Boost预处理器(适用于C和c++,尽管Boost作为一个整体是一个c++库)库可以帮助完成这类任务。它不允许在宏中使用#ifdef,而是帮助您多次包含一个文件,每次定义不同的宏,以便该文件可以使用#ifdef。
The following code, if saved to max.c, should do what you want for each of the words listed in the MAXES #define at the top of the file. However, it won't work if any of the _MAX values are floating point, since the preprocessor can't handle floating point.
下面的代码,如果保存到max。c,应该为文件顶部的MAXES #define中列出的每个词做您想做的事情。但是,如果任何一个_MAX值都是浮点数,那么它就不会起作用,因为预处理器不能处理浮点数。
(Boost Processor is a handy tool, but it's not exactly straightforward; you can decide whether or not this approach is an improvement over copy-and-paste.)
(Boost处理器是一种方便的工具,但并不完全简单;您可以决定这种方法是否优于复制粘贴)。
#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
#2
5
I've tried that before. The problem is that #
is already reserved to stringize a macro parameter. It isn't parsed as a preprocessor token like the one in #
define.
我以前试过。问题是,#已经被保留为对宏参数进行字符串化。它不会像#define中的那样被解析为一个预处理器令牌。
#3
3
The only solution I have is cheating - produce a list of types that have an _XXX_MAX as a set of defines, and then use that. I don't know how to produce the list in automated fashion in preprocessor, so I don't try. The assumption is that the list is not too long and will not be maintained too intensively.
我唯一的解决方法是欺骗——生成一个类型列表,其中有一个_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
#4
0
I don't think it's a case of the ## operator not being allowed in an #ifdef. I tried this:
我不认为##操作符在#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)
}
and it still didn't work (it didn't like #ifdef TYPE). The problem is that #ifdef will only accept #defined symbols, not #define arguments. Those are two different things.
而且它仍然不起作用(它不喜欢#ifdef类型)。问题是#ifdef将只接受#已定义的符号,而不接受#define参数。这是两个不同的东西。
#5
0
Unlike templates, the preprocessor is not turing-complete. An #ifdef
inside a macro is not possible. Your only solution is to make sure you only call print_max
on types which has a matching _MAX
defined, e.g. INT_MAX
. The compiler will surely tell you when they aren't.
与模板不同,预处理器不是turing-complete。在宏内的#ifdef是不可能的。您唯一的解决方案是确保只对定义了匹配_MAX的类型调用print_max,例如INT_MAX。编译器肯定会告诉你什么时候不是。
#6
0
There's no easy way to do this. The closest you can come is to #define a large number of IFDEF macros such as:
要做到这一点并不容易。最接近的方法是#定义大量的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
:
since you need a lot of them (and they might be useful multiple places), it makes a lot of sense to stick all these in their own header file 'ifdefs.h' which you can include whenever you need them. You can even write a script that regenerates ifdef.h from a list of 'macros of interest'
由于您需要很多这样的文件(它们可能在多个地方都很有用),所以将所有这些放在它们自己的头文件ifdefs中是很有意义的。你可以在需要的时候加上h。您甚至可以编写一个重新生成ifdef的脚本。h从一个“宏观利益”列表
Then, your code becomes
然后,代码变得
#include "ifdefs.h"
#define print_max(TYPE) \
IFDEF_##TYPE##_MAX( printf("%lld\n", TYPE##_MAX); )
print_max(INT);
print_max(BLAH);
#1
11
The Boost Preprocessor (which works for C as well as C++, even though Boost as a whole is a C++ library) library can help with this kind of task. Instead of using an #ifdef within a macro (which isn't permitted), it helps you include a file multiple times, with different macros defined each time, so that the file can use #ifdef.
Boost预处理器(适用于C和c++,尽管Boost作为一个整体是一个c++库)库可以帮助完成这类任务。它不允许在宏中使用#ifdef,而是帮助您多次包含一个文件,每次定义不同的宏,以便该文件可以使用#ifdef。
The following code, if saved to max.c, should do what you want for each of the words listed in the MAXES #define at the top of the file. However, it won't work if any of the _MAX values are floating point, since the preprocessor can't handle floating point.
下面的代码,如果保存到max。c,应该为文件顶部的MAXES #define中列出的每个词做您想做的事情。但是,如果任何一个_MAX值都是浮点数,那么它就不会起作用,因为预处理器不能处理浮点数。
(Boost Processor is a handy tool, but it's not exactly straightforward; you can decide whether or not this approach is an improvement over copy-and-paste.)
(Boost处理器是一种方便的工具,但并不完全简单;您可以决定这种方法是否优于复制粘贴)。
#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
#2
5
I've tried that before. The problem is that #
is already reserved to stringize a macro parameter. It isn't parsed as a preprocessor token like the one in #
define.
我以前试过。问题是,#已经被保留为对宏参数进行字符串化。它不会像#define中的那样被解析为一个预处理器令牌。
#3
3
The only solution I have is cheating - produce a list of types that have an _XXX_MAX as a set of defines, and then use that. I don't know how to produce the list in automated fashion in preprocessor, so I don't try. The assumption is that the list is not too long and will not be maintained too intensively.
我唯一的解决方法是欺骗——生成一个类型列表,其中有一个_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
#4
0
I don't think it's a case of the ## operator not being allowed in an #ifdef. I tried this:
我不认为##操作符在#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)
}
and it still didn't work (it didn't like #ifdef TYPE). The problem is that #ifdef will only accept #defined symbols, not #define arguments. Those are two different things.
而且它仍然不起作用(它不喜欢#ifdef类型)。问题是#ifdef将只接受#已定义的符号,而不接受#define参数。这是两个不同的东西。
#5
0
Unlike templates, the preprocessor is not turing-complete. An #ifdef
inside a macro is not possible. Your only solution is to make sure you only call print_max
on types which has a matching _MAX
defined, e.g. INT_MAX
. The compiler will surely tell you when they aren't.
与模板不同,预处理器不是turing-complete。在宏内的#ifdef是不可能的。您唯一的解决方案是确保只对定义了匹配_MAX的类型调用print_max,例如INT_MAX。编译器肯定会告诉你什么时候不是。
#6
0
There's no easy way to do this. The closest you can come is to #define a large number of IFDEF macros such as:
要做到这一点并不容易。最接近的方法是#定义大量的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
:
since you need a lot of them (and they might be useful multiple places), it makes a lot of sense to stick all these in their own header file 'ifdefs.h' which you can include whenever you need them. You can even write a script that regenerates ifdef.h from a list of 'macros of interest'
由于您需要很多这样的文件(它们可能在多个地方都很有用),所以将所有这些放在它们自己的头文件ifdefs中是很有意义的。你可以在需要的时候加上h。您甚至可以编写一个重新生成ifdef的脚本。h从一个“宏观利益”列表
Then, your code becomes
然后,代码变得
#include "ifdefs.h"
#define print_max(TYPE) \
IFDEF_##TYPE##_MAX( printf("%lld\n", TYPE##_MAX); )
print_max(INT);
print_max(BLAH);