简体   繁体   中英

Defining symbolic string constants which have the same name and value

I have a situation where I've got a number of strings that I want to be able to use symbolically, ie as if I'd declared a macro

#define kBlahProperty "kBlahProperty"
#define kFooProperty "kFooProperty"

There are various reasons why I can't use an enum (for more context see this previous question ), such as getting useful info in the debugger, serialising data in a readable format and dealing with sets of properties defined in different source files.

Typical usage:

setProperty(kBlahProperty, 6);
if (otherProperty==kBlahProperty) { doStuff(); }
std::cout << "property type: " << kBlahProperty;  // outputs "kBlahProperty" rather than an enum

There may be many of these properties, and to ease definition I'd like to be able to declare them like this, in one place only:

DEFINE_PROPERTY(kBlahProperty)
DEFINE_PROPERTY(kFooProperty)

However, I can't find a way of defining a macro that will itself expand to #define (I've tried a couple of examples with the '#' and '##' operators, but getting to paste the '#define' is the problem).

An alternative tack was to define the macro to expand as a char* :

#define DEFINE_PROPERTY(propName) const char8* propName=#propName

but this has the problem that it gets defined in each compilation unit and hence linker errors. If I change it to use extern then I can't define it to use the string itself -- that has to go in the .cpp file and so now I would need to declare all these properties in the header and define them again in the cpp file, so you have a list in two places.

So is there a good way of defining these strings so that you can just declare them once? I have access to boost preprocessor, but only to a small subset of C++-0x (so in-class constant initialisers are out).

You can define your macro to have and #ifdef so it has two paths - if and else. Then in the header it just declares your propName. Then in your .cpp file, define a preprocessor variable before you include your header. That define will make your macro define the propName.

Simple (if ugly) way -- define the macro to include extern only if another symbol is not defined, and define that symbol in exactly one compilation unit before you include the header

With example (include guards omitted for clarity)

#ifdef IN_CPP
#define DEFINE_PROPERTY(propName) const char8* propName=#propName;
#else
#define DEFINE_PROPERTY(propName) extern const char8* propName;
#endif

In exactly one compilation unit:

#define IN_CPP 1
#include "header.h"

In remaining compilation units:

#include "header.h"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM