Восстановление модификаторов доступа после макроса

Чтобы объявить список методов, которые необходимы во многих классах нашей кодовой базы, мы используем макрос, такой как этот:

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

Обычно используется так:

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

DECLARE_METHODS();

/*other public members*/

private:
/*private members*/
};

Но известно, что это может привести к хаосу при использовании так:

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

private:
DECLARE_METHODS();

/*private members*/
};

…так как он незаметно объявляет модификатор публичного доступа ко всему, что находится ниже.

Он используется тысячи раз, поэтому замена конечной общедоступной (частной) будет слишком трудоемкой, так как придется перебирать почти все клиенты, чтобы переместить макрос или открыть модификатор общедоступного доступа после него, когда это применимо.
Удаление всех модификаторов и отсутствие защиты bar () не вариант.

Есть ли способ узнать, какой модификатор доступа используется в определенной части кода? Можно ли утверждать, что этот макрос никогда не используется в закрытой области видимости, или как-то запомнить и восстановить правильный модификатор доступа в конце макроса?

3

Решение

Краткий ответ: нет

Причина: Макро-расширение полностью завершается препроцессором еще до того, как любой из с ++ начинает интерпретироваться как с ++.

Это означает, что препроцессор слеп по отношению к коду — это могут быть java, c, text, даже python (если вы не прокомментировали это), и препроцессор с радостью расширит макросы.

То, что вы хотите сделать, может быть достигнуто с помощью любопытно повторяющегося шаблона http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

Например, именно так ATL автоматически реализует для вас общие COM-интерфейсы.

3

Другие решения

Изменить: это на самом деле не работает, отозвали.

Не проверял это (я не использую private) но попробуйте:

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

Это (следует) избегать изменения спецификатора видимости для последующих членов.

-1

По вопросам рекламы [email protected]