是否可以在数值评估后进行字符串化?
是的。以下是我将使用的一些具体定义供参考:
-
算术能够使用常见的原语(例如加法、减法、乘法、除法等)对数字执行计算。
-
表达式 使用常用运算符(如括号分组、中缀运算符 +、-、*、/ 等)的算术语法表示。
算术方法
鉴于这些定义,宏扩展不能计算表达式,但它们可以执行算术运算。您将使用宏而不是运算符,每个宏都将从头开始实现算术。这是使用这种方法的提升 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 表示为 @987654326 @ 而不是 20000)。 Boost pp 算法使用前一种方法(适用于从 0 到 256 的范围;是的,我意识到这是 257 个数字)。
表达方式
或者,您可以评估表达式。如前所述,预处理器可以评估条件指令中的表达式。将其用作原语,您可以梳理出结果;例如,如果 EXPRESSION 扩展为您的表达式,您可以 #define D0,表示结果的个位,使用如下构造:
#if ((EXPRESSION)%10)==9
#define D0 9
#elif ((EXPRESSION)%10)==8
#define D0 8
...
然后您可以类似地将#defineD1 用作十位的特定数字,将D2 用作百位等...然后将RESULT 宏扩展为... D3##D2##D1##D0。将整个事情包装成evaluator.hpp 之类的东西,您可以通过将EXPRESSION 定义为您的表达式,使用#include "evaluator.hpp" 对其进行评估,最后使用RESULT 来表示结果,从而输入任意表达式。使用这种方法,每个“求值器”都需要为特定数字定义的特定 Dx 宏才能工作……因此其行为类似于“变量”,但会消耗整个求值器。
Boost pp 具有此功能,每个评估器称为“插槽”,并提供 5 个插槽。因此,您必须使用#include 进行抽水,并且每个评估者一次只能存储一个结果......但作为回报,您的范围不受限制(超过原生范围)并且您重新实际评估表达式。下面是一个使用 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:范围与本地范围一样开放,使用普通文字
- con:需要 `#include` 来泵送通用机制
- con:重用评估器必须丢失以前的结果