c++预处理器条件参数
C++ preprocessor conditional parameter
请注意c++ 03!任何c++ 11的解决方案都不适合我,但是为了知识的缘故,请把它们贴出来。
我知道预处理器可以做这样的事情:#define FOO 4
#if FOO == 4
cout<<"hi"<<endl;
#endif
我需要的是:
#define BAR(X)
#if X == 4
cout<<"hi"<<endl;
#endif
main.cpp
BAR(4)
我不明白为什么所有需要的信息不能在预处理器时间内提供。
那么,请告诉我如何实现这种行为。
编辑1:正常的if条件对我的情况不起作用,因为我还做了如下操作:
#define BAR(X)
#if X == 4
int poop;
#elif
double poop;
#endif
正如您所发现的,您无法用您尝试过的方式做到这一点。宏展开没有内联条件求值,因此必须创建多个宏。
然而,如果你只是试图"优化"正常的代码流,你可以依靠你的编译器的优化。想想看:
if (true) {
std::cout << "Hin";
}
生成的程序不会有任何条件检查,因为true
总是为真。
if (false) {
std::cout << "Hin";
}
结果程序将不包含任何产生输出的代码,因为false
永远不会为真。
if (4 != 4) {
std::cout << "Hin";
}
程序仍然不包含std::cout
代码。
在许多情况下,您可以使用这个事实来保持代码的简单性并达到您想要的效果:
#define BAR(X)
if ((X) == 4) {
std::cout << "hi" << std::endl;
}
这里的约束,当然,是if
语句必须在您写BAR(5)
、BAR(42)
或BAR(999)
的地方有效。
这也很灵活,因为现在您可以使用运行时值(如BAR(i)
),尽管在编译时不能再折叠条件,但在这种情况下,无论如何您都没有理由期望它。
我在我的日志宏中采用了这种方法:当为LOG_LEVEL_DEBUG
调用宏时,在发布版本中展开为静态已知永远不会匹配的条件。
这个想法是让编译器做优化
您还需要考虑使用一点宏展开技巧来避免后续else
子句的问题。
如果条件参数的值域是已知的(最好是较小的),则可以使用预处理器执行此操作。例如,假设参数只能具有值0和1:
#define DOIT_0(X)
#define DOIT_1(X) X
#define CONCAT_(X, Y) X ## Y
#define MAYBE(X) CONCAT_(DOIT_, X)
#define BAR(X) MAYBE(X)( cout<<"hi"<<endl; )
#define YESNO 0
BAR(YESNO)
Live on coliru.
注意BAR
参数中未受保护的逗号。
对于相等性检查,同样在小范围内:
#define CONCAT3_(X,Y,Z) X ## Y ## Z
#define EQUAL_0_0(X) X
#define EQUAL_1_1(X) X
#define EQUAL_1_1(X) X
#define EQUAL_0_1(X)
#define EQUAL_0_2(X)
#define EQUAL_1_0(X)
#define EQUAL_1_2(X)
#define EQUAL_2_0(X)
#define EQUAL_2_1(X)
#define DO_IF_EQUAL(X, Y) CONCAT3_(EQUAL_, X, Y)
#define BAR(X) DO_IF_EQUAL(X, 2) ( std::cout << "hin"; )
如果您可以使用Boost,那么您可以使用Boost来完成此操作。预处理:
#define BAR(X) BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(X, 4), cout << "hi" << endl;)
这里的一些答案比其他的更好。我接受的那个是Christian Kiewiet在评论中发布的,但它对我的目的来说是最准确的。以下是扩展版本:
useCases.h
enum UseCases{
useCase1=0,
useCase2,
useCaseNumber//always last for iterations
}
specializer.h
#include "useCases.h"
<template UseCases theCase>
struct StaticCase{
//empty, thus accidents calling from this can't happen
}
//specialization
template<>
class StaticCase<UseCases::useCase1>{
typedef int T;
static foo(T arg){cout<<"case1";};
}
template<>
class StaticCase<UseCases::useCase2>{
typedef double T;
static foo(){cout<<"case2";};
}
现在,我可以做
#define BAR1(useCase) StaticCase<useCase>::foo();
或
#define BAR2(useCase) StaticCase<useCase>::T var;
和调用:
BAR1(UseCases::useCase1)//output - case1
BAR1(UseCases::useCase2)//output - case2
- 如果条件,当我想第二个参数时
- 有条件地将默认参数传递给函数(使用"?"运算符)
- 在 constexpr-if 条件下比较 constexpr 函数参数会导致错误
- 用于根据条件选择编译时类型的可变参数模板
- 我可以有条件地使用多个参数吗?
- 在解压缩可变参数模板时避免"recursive"函数调用,直到运行时条件
- 使用 std::条件根据模板参数选择成员类型
- 具有条件的C 模板非类型参数
- 如何避免参数数量依赖于条件的调用分支?
- 有条件的操作员从其参数的副本中返回值
- 根据模板参数条件 C++17 创建成员别名
- 当条件为真时,有没有办法连接宏参数
- C++:无法使用条件类型在模板函数中使用 'double' 类型的 lvalue 初始化 'char*' 类型的参数
- 参数大小可变的函数:如何有条件地设置一些参数?
- 根据数值模板参数有条件地编译转换运算符
- 如果参数条件为 true,则阻止执行返回函数
- 在哪些条件下,我们将指针作为函数参数
- 基于模板类型参数的条件成员签名和实现
- 有条件地将基类引用参数视为派生类并将其返回
- 预处理器和模板参数或代码段的条件编译