开发者

C++ nested macros?

Is there any way, in C++, to define nested macros/constants within a class, in a similiar fashion to nested typedefs, or a method to acheive similiar functionality? The motive is generally 开发者_运维问答for the macros to be used by templates.

class SomeClass
{
public:
    #define SomeConstant 123
};

int x=SomeClass::SomeConstant;

Ofcourse, static const members can do the job, but those are physical variables, while I'm looking for a simple macro-like behavior.


You can't do what you want with macros. Macros have no concept of scoping.

But for simple int values you can do what you want with enums.

class SomeClass
{
public:
    enum {
        SomeConstant=123
        };
};

int x=SomeClass::SomeConstant;

A fully scoped name for the value, but no space taken for it, even in debug builds - you couldn't take its address if you wanted to.


Const values declared and defined in-place are exactly what you need here: the compiler can and will optimise them away completely so they end up being exactly the same as using the #define in the first place, but with the benefits of strict scoping.

class SomeClass {
  public:
   static const int someValue = 10;
};

This doesn't take up any extra space - no memory is allocated to store "someValue". You can prove this: if you try and use the "someValue" as a real object (ie you try and get its address), then the linker will tell you it's undefined.


Macros completely ignore scope - they are expanded before the C++ compilation. You just can't do that.

Use of static const often leads to no variable being allocated - the compiler treats it as a constant.


Macro pre-processors generally don't have any idea of language context; thus they don't know what a "class" is making "nesting inside a class" not make sense in the first place.

For what you want, either use static const, or use the full name (assuming the preprocessor allows colons in macro names, not 100% sure on that) - though it won't allow you to inherit the constant on derived classes:

#define SomeClass::SomeConstant 123


You can do this with templates:

template < int someConstant = 123 > class SomeClass
{
public:
    void outputConstant() { cout << "We think the answer is:" << someConstant; }
}

But that isn't precisely what you want because you have to declare an instance of the class as:

int main(int argc, char *argv)
{
    SomeClass<123> myInstance;
}

I know others have explained the bit about macros, but allow me to add: #define is processed by the pre-processor, not the compiler. In the standard is a section called "translation phases" which explains this in more detail, but for your question the point is that macros are evaluated before the class is even compiled, and the scope at which the #define occurs is not known.

The authoritative book on this subject (programming with templates during the compile stage) is Modern C++ Design: Generic Programming and Design Patterns Applied, by Andrei Alexandrescu.


I don't understand your objection to using a static const. It will not effect the size of your class, and the compiler will optimise to achieve what you think you'd get from a macro.


"Static members are physical variables".

What's against this? The only reason to object to this would be memory usage. But since the member is static, the memory would only be occupied once with the intended content.

On the contrary, with a macro, the contend would be present at every single usage location in the binary.

EDIT: In case the variable is of an integral type, smaller than a pointer, it's probably best to define the constant in the class declaration. Optimizing compilers can then inline the value in the calling code, just like for a macro.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜