我正在使用BOOST_PP来进行预处理器中的预编译计算。我专注于代码大小的应用程序 极其 对我很重要。 (所以请不要说编译器 应该 或者 通常 这样做吗,我需要控制编译时间执行的内容以及生成哪些代码)。但是,我希望能够为整数常数和变量使用相同的宏/函数名称。作为琐碎的例子,我可以

#define TWICE(n) BOOST_PP_MUL(n,2)
//.....
// somewhere else in code
int a = TWICE(5);

这做了我想要的,评估

int a = 10;

在编译时间。

但是,我也希望它在

int b = 5;
int a = TWICE(b);

应该预处理

int b = 5;
int a = 5 * 2;

当然,我可以使用传统的宏来这样做

#define TWICE(n) n * 2

但是,它并没有为整数常数(在编译时间评估它们)做我想做的事情。

因此,我的问题是,是否有一个技巧可以检查该参数是文字还是变量,然后使用不同的定义。即,这样的事情:

#define TWICE(n) BOOST_PP_IF( _IS_CONSTANT(n), \
                              BOOST_PP_MUL(n,2), \
                              n * 2 )

编辑:因此,我真正追求的是某种方法来检查在编译时是否可以使用常数,因此对于BOOST_PP_函数来说是一个很好的论点。我意识到,这与大多数人对预处理器和一般编程建议的期望不同。但是没有 错误的 编程方式,因此,如果您不同意其哲学,请不要讨厌这个问题。 BOOST_PP库存在是有原因的,这个问题也具有同样的精神。不过,这可能是不可能的。

有帮助吗?

解决方案

您正在尝试做一些更好的编译器优化的事情。

int main (void) {
  int b = 5;
  int a = b * 2;

  return a; // return it so we use a and it's not optimized away
}

GCC -O3 -S TC

 .file "t.c"
 .text
 .p2align 4,,15
.globl main
 .type main, @function
main:
.LFB0:
 .cfi_startproc
 movl $10, %eax
 ret
 .cfi_endproc
.LFE0:
 .size main, .-main
 .ident "GCC: (Debian 4.5.0-6) 4.5.1 20100617 (prerelease)"
 .section .note.GNU-stack,"",@progbits

优化编译器将优化。

编辑:我知道您不想听到编译器“应该”或“通常”这样做。但是,您要做的不是在C预处理器中要做的事情。设计C语言和C预处理器的人将其设计为与基本原子的预处理令牌一起工作。 CPP在许多方面都是“愚蠢”。这不是一件坏事(实际上,在许多情况下,这使它如此有用),但是归根结底,它是预处理人。在解析源文件之前,它会预先处理源文件。在语义分析发生之前,它会预处理源文件。在检查给定源文件的有效性之前,它会预处理源文件。我知道您不想听到这是解析器和语义分析仪应该处理或通常做的事情。但是,这是情况的现实。如果您想设计非常小的代码,那么您应该依靠编译器来完成工作,而不是尝试创建预处理器构造来完成工作。这样想:数千个小时的工作进入了您的编译器,因此请尝试重复使用尽可能多的工作!

其他提示

但是,不是很直接的方法:

struct operation {
    template<int N>
    struct compile {
        static const int value = N;
    };
    static int runtime(int N) { return N; }
};

operation::compile<5>::value;
operation::runtime(5);

或者

operation<5>();
operation(5);

没有真正的机会混合两个级别(预处理器和评估 变量)。根据我从您的问题中了解的, b 应该是象征性常数吗?

我认为您应该使用传统的

#define TWICE(n) ((n) * 2)

但是,您应该使用编译时间常数初始化它们,而不是用表达式初始化变量。我看到的唯一在编译时强制评估并在C中具有符号常数的是积分枚举常数。这些定义为类型 int 并在编译时进行评估。

enum { bInit = 5 };
int b = bInit;
enum { aInit = TWICE(bInit) };
int a = aInit; 

通常,你不应该太节俭 const (至于你 b),并用 -S.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top