macro dependent macro

半世苍凉 提交于 2020-01-14 09:21:09

问题


Is it possible to do something like this:

  #define F(x) \
    #ifdef DOUBLE \
      2*x \
    #else \
      x \
    #endif

so that when I use F, what it expands to depends on whether the macro DOUBLE is defined? I don't think so, but I'm hopeful. GNU expansions are fine.

Edit In response to some of the answers, I'm really using this to do some code generation, where the code is slightly different depending on where it gets defined. Because of the order in which some files are included and where the relevant macros need to be defined, switching it around that way requires a bit of factoring. I may have to do it, but would be thrilled if I don't have to unpaint myself from this corner!


回答1:


If we can constrain the problem, you can accomplish this. Specifically, if you can guarantee that DOUBLE is either

  • not defined as a macro, or
  • is defined as a macro that expands to an empty token sequence (e.g. #define DOUBLE),

then you can use an indirect approach with token concatenation:

#define F_IMPL_(x)       DOUBLE_IS_DEFINED
#define F_IMPL_DOUBLE(x) DOUBLE_NOT_DEFINED

#define F_1(x, m) F_2(x, m)
#define F_2(x, m) F_IMPL_ ## m ( x )

#define F(x) F_1(x, DOUBLE)

Usage example:

F(t)
#define DOUBLE
F(t)

Result after preprocessing:

DOUBLE_NOT_DEFINED
DOUBLE_IS_DEFINED

This approach will also work if DOUBLE (if it is defined) is defined as a macro that expands to a single known token, if that token can form part of an identifier (e.g., TRUE or 1). To handle this, you just have to rename the F_IMPL_ macro to F_IMPL_{TOKEN} (e.g., F_IMPL_TRUE or F_IMPL_1).




回答2:


What's wrong with

#ifdef DOUBLE
  #define F(x) (2 * (x))
#else
  #define F(x) (x)
#endif



回答3:


Why not do the nesting the other way around?

#ifdef DOUBLE
#define F(x) (2*(x))
#else
#define F(x) (x)
#endif 



回答4:


No. The closest thing you can do is to put that in a header file, and #include that header file each time the definitions you care about change. This is sometimes called the "X" pattern, because X is used as a macro that changes definition.

For example, one common usage of that pattern is to autogenerate the string names of enum values:

// File myenum_values.h
// NOTE: _no_ header guards so we can include this file multiple times
X(Apple)
X(Orange)
X(banana)

// File myenum.h
enum Fruit
{
#define X(x) x,
#include "myenum_values.h"
}

const char *FruitNames[] =
{
#undef X
#define X(x) #x,
#include "myenum_values.h"
};

// We now have an array of fruit names without having to define the enum twice


来源:https://stackoverflow.com/questions/4927976/macro-dependent-macro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!