预处理器宏代码中的语法错误

发布于 2024-10-24 10:31:06 字数 2062 浏览 1 评论 0原文

我正在尝试为返回字符串长度的宏编写一些代码,并尝试使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧夏天 2024-10-31 10:31:06

这个怎么样 - http://codepad.org/aT7SK1Lu
它仍然是编译时 strlen,并且编译速度可能会快得多。

#include <stdio.h>
#include <string.h>

#define TEST_STRING "Hello, World!"

template <int N> struct xtmp2 { typedef char (&t)[N]; };
template< class T, int N > typename xtmp2<N>::t xlen( T (&)[N] );
#define STRLEN(x) (sizeof(xlen(x))-1)

int main( void ) {

  printf( "strlen(\"%s\") = %i %i\n", TEST_STRING, STRLEN(TEST_STRING), strlen(TEST_STRING) );
}

对于宏调试,可以获得预处理器输出(如 gcc -E);
取消大多数宏的定义,然后一一启用它们也可能会有所帮助
看看会发生什么。

How about this - http://codepad.org/aT7SK1Lu
Its still a compile-time strlen, and would be likely much faster to compile.

#include <stdio.h>
#include <string.h>

#define TEST_STRING "Hello, World!"

template <int N> struct xtmp2 { typedef char (&t)[N]; };
template< class T, int N > typename xtmp2<N>::t xlen( T (&)[N] );
#define STRLEN(x) (sizeof(xlen(x))-1)

int main( void ) {

  printf( "strlen(\"%s\") = %i %i\n", TEST_STRING, STRLEN(TEST_STRING), strlen(TEST_STRING) );
}

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.

心碎无痕… 2024-10-31 10:31:06

如果这是一个无关紧要的指出,请原谅我。
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 whether
the character is '\0' at compile-time(runtime?).
So, I think it is difficult to accomplish the goal directly with string
literal "Hello, World!".

涙—继续流 2024-10-31 10:31:06

它不起作用,原因很简单:预处理器不应该处理文字。

预处理器只知道“标记”,它可以连接它们,可以将其转换为字符串文字,并且可以操作宏替换,但仅此而已。

在这里,停止循环的条件(使用 []==)最多可以由编译器执行(最有可能在运行时),因此不适合BOOST_PP_WHILE

实际上,您可以使用编译器来获取数组(此处为字符数组)的元素数量:

例如使用 sizeofsizeof(array)/sizeof(array[0 ])。这可以在宏中抽象,但是它不能成为“常规”函数,因为数组不能传递给“常规”函数,只能传递给指针(您丢失了信息大小)。

您还可以使用模板函数:(

template <typename T, size_t N>
size_t size(T (&)[N]) { return N; }

这实际上适用于具有恒定大小的任何数组)

但是,对于您自己的问题,您会很高兴知道大多数编译器都有内置的 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 for BOOST_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:

template <typename T, size_t N>
size_t size(T (&)[N]) { return N; }

(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.

無處可尋 2024-10-31 10:31:06

我想知道它是否应该是这样的:

#include <stdio.h>
#include <string.h>

#define TEST_STRING "Hello, World!"

#define STRLEN(x)    (x[0]==0)?0:TEST_01(x,1)
#define TEST_01(x,y) (x[y]==0)?y:TEST_02(x,y+1)
#define TEST_02(x,y) (x[y]==0)?y:TEST_03(x,y+1)
#define TEST_03(x,y) (x[y]==0)?y:TEST_04(x,y+1)
#define TEST_04(x,y) (x[y]==0)?y:TEST_05(x,y+1)
#define TEST_05(x,y) (x[y]==0)?y:TEST_06(x,y+1)
#define TEST_06(x,y) (x[y]==0)?y:TEST_07(x,y+1)
#define TEST_07(x,y) (x[y]==0)?y:TEST_08(x,y+1)
#define TEST_08(x,y) (x[y]==0)?y:TEST_09(x,y+1)
#define TEST_09(x,y) (x[y]==0)?y:TEST_10(x,y+1)
#define TEST_10(x,y) (x[y]==0)?y:TEST_11(x,y+1)
#define TEST_11(x,y) (x[y]==0)?y:TEST_12(x,y+1)
#define TEST_12(x,y) (x[y]==0)?y:TEST_13(x,y+1)
#define TEST_13(x,y) (x[y]==0)?y:TEST_14(x,y+1)
#define TEST_14(x,y) (x[y]==0)?y:TEST_15(x,y+1)
#define TEST_15(x,y) (x[y]==0)?y:TEST_16(x,y+1)
#define TEST_16(x,y) (x[y]==0)?y:TEST_17(x,y+1)
#define TEST_17(x,y) (x[y]==0)?y:TEST_18(x,y+1)
#define TEST_18(x,y) (x[y]==0)?y:TEST_19(x,y+1)
#define TEST_19(x,y) (x[y]==0)?y:-1

int main( void ) {
  printf( "strlen(\"%s\") = %i %i\n", TEST_STRING, STRLEN(TEST_STRING), strlen(TEST_STRING) );
}

但这不是编译时评估,尽管它通常是
优化为常数。

I wonder if it was supposed to be something like this:

#include <stdio.h>
#include <string.h>

#define TEST_STRING "Hello, World!"

#define STRLEN(x)    (x[0]==0)?0:TEST_01(x,1)
#define TEST_01(x,y) (x[y]==0)?y:TEST_02(x,y+1)
#define TEST_02(x,y) (x[y]==0)?y:TEST_03(x,y+1)
#define TEST_03(x,y) (x[y]==0)?y:TEST_04(x,y+1)
#define TEST_04(x,y) (x[y]==0)?y:TEST_05(x,y+1)
#define TEST_05(x,y) (x[y]==0)?y:TEST_06(x,y+1)
#define TEST_06(x,y) (x[y]==0)?y:TEST_07(x,y+1)
#define TEST_07(x,y) (x[y]==0)?y:TEST_08(x,y+1)
#define TEST_08(x,y) (x[y]==0)?y:TEST_09(x,y+1)
#define TEST_09(x,y) (x[y]==0)?y:TEST_10(x,y+1)
#define TEST_10(x,y) (x[y]==0)?y:TEST_11(x,y+1)
#define TEST_11(x,y) (x[y]==0)?y:TEST_12(x,y+1)
#define TEST_12(x,y) (x[y]==0)?y:TEST_13(x,y+1)
#define TEST_13(x,y) (x[y]==0)?y:TEST_14(x,y+1)
#define TEST_14(x,y) (x[y]==0)?y:TEST_15(x,y+1)
#define TEST_15(x,y) (x[y]==0)?y:TEST_16(x,y+1)
#define TEST_16(x,y) (x[y]==0)?y:TEST_17(x,y+1)
#define TEST_17(x,y) (x[y]==0)?y:TEST_18(x,y+1)
#define TEST_18(x,y) (x[y]==0)?y:TEST_19(x,y+1)
#define TEST_19(x,y) (x[y]==0)?y:-1

int main( void ) {
  printf( "strlen(\"%s\") = %i %i\n", TEST_STRING, STRLEN(TEST_STRING), strlen(TEST_STRING) );
}

But this isn't a compile-time evaluation, even though it would be usually
optimized to a constant.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文