预处理器宏代码中的语法错误
我正在尝试为返回字符串长度的宏编写一些代码,并尝试使用 BOOST_PP_WHILE 来实现它。该代码源于以下事实:宏参数 foo
表示的字符串的 position
指定位置处的字符可以通过 #foo[position] 获得
。使用 MSVC 或 Intel C++ 进行编译会导致类似的语法错误;如果您能指出代码为何生成这些语法错误以及我将如何纠正代码,我们将不胜感激。 我知道这些错误是由 PREDICATE
宏中的代码引起的,但我尝试在其中使用的任何表达式(除了 BOOST_PP_TUPLE_ELEM
)都会导致编译时错误.
错误:
prog.cpp:47:1: error: pasting "BOOST_PP_BOOL_" and ""\"Hello, World!\""" does not give a valid preprocessing token
prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:47: error: ‘BOOST_PP_TUPLE_ELEM_2_1’ was not declared in this scope
正如人们所预料的那样,行号并不是很有用,因为它们都指向调用宏 MACRO_STRLEN
的行。
代码
下面是我尝试实现我所描述的宏的源列表。
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/control/while.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <cstdio>
#define TEST_STRING0 "Hello, World!"
#define MACRO_IS_NULL_IMPL(x, position) \
#x[position] == '\0'
#define MACRO_IS_NULL(x, position) \
MACRO_IS_NULL_IMPL(x, position)
#define PREDICATE_D(string, position) \
MACRO_IS_NULL(string, position)
#define PREDICATE(n, state) \
PREDICATE_D( \
BOOST_PP_TUPLE_ELEM(2, 0, state), \
BOOST_PP_TUPLE_ELEM(2, 1, state) \
)
#define OPERATION_D(string, position) \
( \
string, \
BOOST_PP_INC(position) \
)
#define OPERATION(d, state) \
OPERATION_D( \
BOOST_PP_TUPLE_ELEM(2, 0, state), \
BOOST_PP_TUPLE_ELEM(2, 1, state) \
)
#define MACRO_STRLEN_IMPL(string) \
BOOST_PP_TUPLE_ELEM( \
2, 1, BOOST_PP_WHILE(PREDICATE, OPERATION, (string, 0)) \
)
#define MACRO_STRLEN(string) \
MACRO_STRLEN_IMPL(string)
int main(int argc, char ** argv) {
printf("String length: %d.\n", MACRO_STRLEN(TEST_STRING0));
return 0;
}
I am trying to write some code for a macro which returns the length of a string, and am attempting to implement it using BOOST_PP_WHILE. The code stems from the fact that a character at a position specified by position
of the string represented by a macro argument foo
may be obtained by #foo[position]
. Compiling using either MSVC or Intel C++ results in similar syntax errors; if you could point out why the code is generating these syntax errors and how I would rectify code, it would be greatly appreciated. I know that the errors are caused by the code within the PREDICATE
macro, but any expression I attempt to use within it barring BOOST_PP_TUPLE_ELEM
results in a compile-time error.
Errors:
prog.cpp:47:1: error: pasting "BOOST_PP_BOOL_" and ""\"Hello, World!\""" does not give a valid preprocessing token
prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:47: error: ‘BOOST_PP_TUPLE_ELEM_2_1’ was not declared in this scope
As one would expect, the line numbers are not very useful since both point to the line at which the macro MACRO_STRLEN
is called.
Code
Below follows the source listing in which I attempt to implement the macro which I describe.
#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/control/while.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <cstdio>
#define TEST_STRING0 "Hello, World!"
#define MACRO_IS_NULL_IMPL(x, position) \
#x[position] == '\0'
#define MACRO_IS_NULL(x, position) \
MACRO_IS_NULL_IMPL(x, position)
#define PREDICATE_D(string, position) \
MACRO_IS_NULL(string, position)
#define PREDICATE(n, state) \
PREDICATE_D( \
BOOST_PP_TUPLE_ELEM(2, 0, state), \
BOOST_PP_TUPLE_ELEM(2, 1, state) \
)
#define OPERATION_D(string, position) \
( \
string, \
BOOST_PP_INC(position) \
)
#define OPERATION(d, state) \
OPERATION_D( \
BOOST_PP_TUPLE_ELEM(2, 0, state), \
BOOST_PP_TUPLE_ELEM(2, 1, state) \
)
#define MACRO_STRLEN_IMPL(string) \
BOOST_PP_TUPLE_ELEM( \
2, 1, BOOST_PP_WHILE(PREDICATE, OPERATION, (string, 0)) \
)
#define MACRO_STRLEN(string) \
MACRO_STRLEN_IMPL(string)
int main(int argc, char ** argv) {
printf("String length: %d.\n", MACRO_STRLEN(TEST_STRING0));
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这个怎么样 - http://codepad.org/aT7SK1Lu
它仍然是编译时 strlen,并且编译速度可能会快得多。
对于宏调试,可以获得预处理器输出(如 gcc -E);
取消大多数宏的定义,然后一一启用它们也可能会有所帮助
看看会发生什么。
How about this - http://codepad.org/aT7SK1Lu
Its still a compile-time strlen, and would be likely much faster to compile.
As to macro debug, its possible to get a preprocessor output (like gcc -E);
it may be also helpful to undefine most macros, then enable them one by one to
see what happens.
如果这是一个无关紧要的指出,请原谅我。
BOOST_PP_WHILE
的谓词在预处理时进行评估。但是,如果我理解正确的话,
MACRO_IS_NULL_IMPL
确定是否该字符在编译时(运行时?)为
'\0'
。所以,我认为直接用string来完成目标是很难的
文字
“你好,世界!”
。Please forgive me if this is an irrelevant pointing out.
The predicate for
BOOST_PP_WHILE
is evaluated while preprocess.However, if I understand correctly,
MACRO_IS_NULL_IMPL
determines whetherthe character is
'\0'
at compile-time(runtime?).So, I think it is difficult to accomplish the goal directly with string
literal
"Hello, World!"
.它不起作用,原因很简单:预处理器不应该处理文字。
预处理器只知道“标记”,它可以连接它们,可以将其转换为字符串文字,并且可以操作宏替换,但仅此而已。
在这里,停止循环的条件(使用
[]
和==
)最多可以由编译器执行(最有可能在运行时),因此不适合BOOST_PP_WHILE
。实际上,您可以使用编译器来获取数组(此处为字符数组)的元素数量:
例如使用
sizeof
:sizeof(array)/sizeof(array[0 ])
。这可以在宏中抽象,但是它不能成为“常规”函数,因为数组不能传递给“常规”函数,只能传递给指针(您丢失了信息大小)。您还可以使用模板函数:(
这实际上适用于具有恒定大小的任何数组)
但是,对于您自己的问题,您会很高兴知道大多数编译器都有内置的
strlen
在编译时评估的常量的实现。It won't work, and for a simple reason: the preprocessor is not meant to deal with literals.
The preprocessor only knows about "tokens", it can catenate them, it can transform one into a string literal, and it can operate macros replacements, but that's it.
Here, the condition to stop the loop (use of
[]
and==
) could be, at best, executed by the compiler (and most likely at runtime), therefore is not suitable forBOOST_PP_WHILE
.You can, actually, use the compiler to get the number of elements of an array (here an array of characters):
For example using
sizeof
:sizeof(array)/sizeof(array[0])
. This can be abstracted in a macro, however it cannot become a "regular" function, since arrays cannot be passed to "regular" functions, only pointers (where you've lost the information size).You can also use a template function:
(this actually work on any array with a constant size)
But, for your own issue, you'll be pleased to know that most compilers have a built-in
strlen
implementation for constants that evaluates at compile-time.我想知道它是否应该是这样的:
但这不是编译时评估,尽管它通常是
优化为常数。
I wonder if it was supposed to be something like this:
But this isn't a compile-time evaluation, even though it would be usually
optimized to a constant.