C 预处理器字符串化(再次)

C Preprocessor stringification (again)

stringification数值评估后是否可以

用一个简单的例子可以更好地解释这一点:

#define A 1
#define B 2
#define SUM (A + B)

#define STR_IMPL_(x) #x
#define STR(x) STR_IMPL_(x)

char *sum = STR(SUM);

正如所写,这会生成单行:

char *sum = "(1 + 2)";

是否有可能以某种方式生成 char *sum = "3";

我怀疑这是不可能的,因为 CPP 是一个纯文本处理器(尽管它 可以 做算术运算,至少在条件语句中是这样),但我可能忽略了一些东西。

#include <boost/preprocessor/arithmetic/add.hpp>

char* sum = STR(BOOST_PP_ADD(A,B));
Is it possible to have stringification after numeric evaluation?

是的。作为参考,这里有一些我将使用的具体定义:

  • 算术使用加、减、乘、除等常用原语对数字进行计算的能力
  • 表达式使用括号分组、中缀运算符+、-、*、/等常用运算符的算术语法表示

算术方法

鉴于这些定义,宏展开不能计算表达式,但它们可以执行算术运算。您可以使用宏代替运算符,每个宏都会从头开始实现算术。这是使用这种方法的 boost pp 用法:

#include <boost/preprocessor/arithmetic.hpp>
#include <boost/preprocessor/stringize.hpp>

#define A 1
#define B 2
#define SUM BOOST_PP_ADD(A, B)
BOOST_PP_STRINGIZE(SUM)

Demo

使用这种方法,您只需将宏扩展为结果即可;然后可以将该结果字符串化。但是你是在宏中实现算术本身而不是运算符,这需要很多宏。因此,要做到这一点,要么 您的数字范围需要严格限制, 您需要使用可分解为宏观评估的数字(例如, 将 20000 表示为 (2,0,0,0,0) 而不是 20000)。 Boost pp 算法使用前一种方法(适用于从 0256 的范围;是的,我知道那是 257 个数字)。

表达方式

或者,您可以计算表达式。如前所述,预处理器可以评估条件指令中的表达式。将其用作原语,您可以梳理出结果;例如,如果 EXPRESSION 扩展为您的表达式,您可以 #define D0,表示结果的单位数字,使用如下结构:

#if   ((EXPRESSION)%10)==9
#define D0 9
#elif ((EXPRESSION)%10)==8
#define D0 8
...

然后你可以类似地 #define D1 是十位的特定数字,D2 是百位,等等......然后有一个 RESULT宏展开为 ... D3##D2##D1##D0。将整个东西包装成 evaluator.hpp 之类的东西,你可以通过将 EXPRESSION 定义为你的表达式,使用 #include "evaluator.hpp" 来计算它,最后使用 RESULT 来输入任意表达式表示结果。使用这种方法,每个 "evaluator" 都需要为特定数字定义的特定 Dx 宏才能工作...因此其行为类似于 "variables",但会消耗整个计算器。

Boost pp 具有此功能,每个评估器称为 "slot",并提供 5 个插槽。所以你必须用 #include 抽水,每个评估者一次只能存储一个结果......但在 return 中你的范围是 not 限制(超过本机范围)并且您实际上是在评估表达式。这是使用 boost pp 使用此方法的示例:

#include <boost/preprocessor/slot/slot.hpp>
#include <boost/preprocessor/stringize.hpp>

#define A 1
#define B 2
#define SUM (A+B)

#define BOOST_PP_VALUE SUM
#include BOOST_PP_ASSIGN_SLOT(1)

BOOST_PP_STRINGIZE(BOOST_PP_SLOT(1))

Demo

(编辑:手动计算器 here (wandbox) 可能值得回顾一下,看看上面解释的机制是如何工作的)。

TL;DR 摘要

    • 算术
    • pro: 完全通过宏调用求值
    • con: 宏而不是中缀运算符
    • con:范围有限或使用替代文字表示
    • 表达式
    • pro:评估实际表达式(中缀、组等)
    • pro: ranges as open as native ranges, with 普通文字
    • con: 需要 `#include` 来抽取通用机制
    • con:重用求值器必须丢失之前的结果