C++ C++;预处理器条件参数

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 我不明白为什么所有需要的信息在预处理器时间内都不可用 所以

请注意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
我不明白为什么所有需要的信息在预处理器时间内都不可用

所以,请告诉我如何实现这种行为


编辑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