开发者

macro dependent macro

开发者 https://www.devze.com 2023-02-09 07:14 出处:网络
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\

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, 开发者_JAVA技巧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!


What's wrong with

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


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).


Why not do the nesting the other way around?

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


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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号