Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
204 views
in Technique[技术] by (71.8m points)

Is there a way to write a C/C++ function-like macro that tests if an object-like macro is defined and generates code uses it?

I can find other questions on the site about using #if and #ifdef inside macros, and ways to get around the restriction to achieve various things, but none of them or their answers seem to match my use-case, which seems like an obvious one to me:

// the system flags are defined as object-like macros in this header...
#include <sys/stat.h>

// naive attempt at function-like macro that of course cannot work
#define MAYBE_EXPORT_FLAG(flag)                
  #if defined(flag).                           
    exports.Set(Napi::String::New(env, #flag), 
                Napi::Number::New(env, flag)); 
  #endif


Napi::Object Init(Napi::Env env, Napi::Object exports) {
    MAYBE_EXPORT_FLAG(UF_NODUMP)
    MAYBE_EXPORT_FLAG(UF_IMMUTABLE)
    MAYBE_EXPORT_FLAG(UF_APPEND)

    return exports;
}

For instance, this previous question seems similar and a workaround is provided, but I couldn't adapt that set of macros to my case, or if it is adaptable I'm not understanding something there. In any case it doesn't use the macro's parameter in the generated code.

I did find that there were some tricks around to do what some of the other questions wanted but I couldn't find a way to adapt any of them to this case. But they are quite tricky. So is there some trick or is it simply impossible?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

What you end up needing to do is define a macro for every symbol of interest that expands based on whether the symbol is defined:

#include <sys/stat.h>

#ifdef UF_NODUMP
#define IFDEF_UF_NODUMP(...)  __VA_ARGS__
#else
#define IFDEF_UF_NODUMP(...)
#endif
#ifdef UF_IMMUTABLE
#define IFDEF_UF_IMMUTABLE(...)  __VA_ARGS__
#else
#define IFDEF_UF_IMMUTABLE(...)
#endif
#ifdef UF_APPEND
#define IFDEF_UF_APPEND(...)  __VA_ARGS__
#else
#define IFDEF_UF_APPEND(...)
#endif

#define MAYBE_EXPORT_FLAG(flag)                    
    IFDEF_ ## flag(                                
        exports.Set(Napi::String::New(env, #flag), 
                    Napi::Number::New(env, flag)); 
    )

Napi::Object Init(Napi::Env env, Napi::Object exports) {
    MAYBE_EXPORT_FLAG(UF_NODUMP)
    MAYBE_EXPORT_FLAG(UF_IMMUTABLE)
    MAYBE_EXPORT_FLAG(UF_APPEND)

    return exports;
}

This is somewhat painful and repetitive, but you can put all the repeated stuff in its own header file somewhere that you don't need to refer to much. Depending on what you are are trying to do, you might find it useful to define IFNDEF_ macros for each symbol as well.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...