C++ C++;预处理器条件参数
请注意C++03!任何C++11解决方案对我来说都不好,但一定要发布它们,只是为了知识 我知道预处理器可以执行以下操作:C++ C++;预处理器条件参数,c++,if-statement,c-preprocessor,c++03,C++,If Statement,C Preprocessor,C++03,请注意C++03!任何C++11解决方案对我来说都不好,但一定要发布它们,只是为了知识 我知道预处理器可以执行以下操作: #define FOO 4 #if FOO == 4 cout<<"hi"<<endl; #endif #define BAR(X)\ #if X == 4\ int poop; #elif double poop; #endif 我不明白为什么所有需要的信息在预处理器时间内都不可用 所以
#define FOO 4
#if FOO == 4
cout<<"hi"<<endl;
#endif
#define BAR(X)\
#if X == 4\
int poop;
#elif
double poop;
#endif
我不明白为什么所有需要的信息在预处理器时间内都不可用
所以,请告诉我如何实现这种行为
编辑1: 正常的if条件对我的情况不起作用,因为我也会这样做:
#define FOO 4
#if FOO == 4
cout<<"hi"<<endl;
#endif
#define BAR(X)\
#if X == 4\
int poop;
#elif
double poop;
#endif
正如你所发现的,你不能以你所尝试的方式来做这件事。宏扩展没有内联条件求值,因此必须创建多个宏 然而,如果您只是试图“优化”正常的代码流,那么您可以依赖于编译器的优化。考虑这一点:
if (true) {
std::cout << "Hi\n";
}
生成的程序将不包含任何生成输出的代码,因为false
从来都不是真的
同样地:
if (false) {
std::cout << "Hi\n";
}
if (4 != 4) {
std::cout << "Hi\n";
}
当然,这里的限制条件是if
语句必须在您编写BAR(5)
或BAR(42)
或BAR(999)
的位置有效
这也很灵活,因为现在您可以使用运行时值(如BAR(i)
),尽管在编译时不再可以折叠条件,但在这种情况下,您没有理由期望这样做
我在日志宏中采用了这种方法:在发布版本中,当为LOG\u LEVEL\u DEBUG
调用宏时,该宏将扩展为静态已知的永远不匹配的条件
想法是让编译器进行优化。
你也要考虑使用.
如果你可以使用Boost,你可以这样做:
#define BAR(X)BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(X,4),cout如果条件参数的值域是已知的(最好是较小的),则可以使用预处理器执行此操作。例如,假设参数只能具有值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)
这里的一些答案比其他的好。
我接受的那封信是Christian Kiewiet在一篇评论中发表的,但它对我来说是最准确的。
以下是扩展版本:
用例
enum UseCases{
useCase1=0,
useCase2,
useCaseNumber//always last for iterations
}
特化器
#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";};
}
但是为什么你需要使用预处理器呢?一个正常的if条件可能也会起作用…?你可能想显示更多的代码/你正在尝试做什么。根据你给出的代码示例,我想我可能建议使用一个模板,而不是给出一个纯宏解决方案?取决于它会使其他事情变得多么复杂。从你对问题的第一次编辑,这不是很关键吗?template struct BAR{typedef double t;};template struct BAR{typedef int t;};BAR::t intPoop;BAR::t doublePoop;
@πάνταῥεῖ: 什么?完全是胡说八道。你又在这里胡闹了。我重新开始这个问题,因为你完全错了。BAR(I)
和BAR(4)
是完全不同的用例。谢谢。这对于优化目的来说确实很好,但这里不是这样。我添加了适合我需要的答案。它是如何在那里实现的?@Gulzar你不想知道。你真的不想知道;-)但是如果你仍然想知道,你可以自己寻找-毕竟它是开源的。我恐怕没有简单的方法来总结它-这是预处理器的黑魔法。这是一个非常好的解决方案,但不是很漂亮,也不是可扩展的解决方案,但是+1因为它回答了这个问题。Thanks@GulzarFWIW,这就是Boost.预处理器在内部实现的方式。除了值的范围通常为0..256,并且有些可配置。
#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 << "hi\n"; )
enum UseCases{
useCase1=0,
useCase2,
useCaseNumber//always last for iterations
}
#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