Restoring access modifiers after a macro

To declare a list of methods needed in many of the classes in our codebase, we use a macro such as this one:

#define DECLARE_METHODS()             \
    public:                           \
        virtual void foo1(/*args*/);  \
        virtual void foo2(/*args*/);  \
        [...]                         \
    protected:                        \
        virtual void bar(/*args*/);   \
    public:

      

It is commonly used as follows:

class Class
{
public:
    Class();
    ~Class();

    DECLARE_METHODS();

    /*other public members*/

private:
    /*private members*/
};

      

But it was known to cause havoc when used like this:

class Class
{
public:
    Class();
    ~Class();

private:
    DECLARE_METHODS();

    /*private members*/
};

      

... as it covertly declares a public modifier to everything below it.

It has been used thousands of times, so replacing the target public with: private: would be too time consuming as it would have to go to almost all clients to move the macro or open the public modifier after it, when applicable. Removing all modifiers and having bar () unprotected is not an option.

Is there a way to find out which access modifier is used in a specific part of the code? Is it safe to argue that this macro is never used in the non-public area, or somehow remember and restore the correct access modifier at the end of the macro?

+3


source to share


2 answers


Short answer: No

Reason: The expansion of the macro is fully pre-processed before any of C ++ even starts being interpreted as C ++.

This means the pre-processor is code-blind - it could be java, c, text, and even python (if you haven't commented it), and the pre-processor will happily extend macros.



What you want to do can be achieved with the curiously repeating pattern template http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

For example, this is how ATL automatically implements common COM interfaces for you.

+3


source


Edit: this doesn't actually work, sucked in.

Haven't tested this (I am not using private

) but try:



#define DECLARE_METHODS() \
    public virtual void foo1(/*args*/); \
    public virtual void foo2(/*args*/); \
    [...] \
    protected virtual void bar(/*args*/); \
    /* done */

      

This (should) avoid changing the visibility specifier for subsequent members.

-1


source







All Articles