Поиск шаблона выписки в файле c ++ - PullRequest
2 голосов
/ 30 декабря 2008

У меня есть макрос, который выглядит так:

#define coutError    if (VERBOSITY_SETTING >= VERBOSITY_ERROR)    ods()

где ods () - это класс, который ведет себя подобно cout, а VERBOSITY_SETTING - глобальная переменная. Есть несколько из них для различных настроек многословия, и это позволяет коду выглядеть примерно так:

if (someErrorCondition)
{
    // ... do things relating to the error condition ...

    coutError << "Error condition occurred";
}

И в этом фреймворке есть функциональные возможности для настройки многословия и т. Д. Однако очевидный шаблон ломается, если не использовать фигурные скобки в чем-то вроде этого:

void LightSwitch::TurnOn()
{
    if (!PowerToSwitch)
        coutError << "No power!";
    else
        SwitchOn = true;
}

из-за макроса превратится в это:

void LightSwitch::TurnOn()
{
    if (!PowerToSwitch)
        if (VERBOSITY_SETTING >= VERBOSITY_ERROR)
            ods() << "No power!";
        else
            SwitchOn = true;
}

Что не является предполагаемой функциональностью оператора if.

Теперь я понимаю способ правильно исправить этот макрос, чтобы он не вызывал этой проблемы, но я бы хотел провести аудит кода и найти любое место с таким шаблоном "if (..." ) coutError << ...; еще ", чтобы выяснить, есть ли другие случаи, когда это происходит, чтобы убедиться, что при исправлении макроса действительно будут правильные функции. </p>

Я могу использовать любой язык / инструмент, чтобы найти это, я просто хочу знать лучший способ сделать это.

Ответы [ 6 ]

2 голосов
/ 30 декабря 2008

Не пытайтесь найти все места в вашем коде, где происходит логическая ошибка - устраните проблему в ее источнике! Измените макрос, чтобы исключить возможность ошибки:

#define coutError if(VERBOSITY_SETTING < VERBOSITY_ERROR); else ods()

Обратите внимание, что здесь я перевернул тест, добавил пустой оператор для предложения then и поместил выходной объект в предложение else. Это все еще позволяет вам использовать << foo << bar после макроса, и если у вас есть конечное предложение else, принадлежащее другому оператору if, оно будет сопоставлено должным образом, так как оно расширяется так:

if(foo)
    coutError << bar;
else
    baz();

становится

if(foo)
    if(VERBOSITY_SETTING < VERBOSITY_ERROR)
        ;
    else
        ods() << bar;
else
    baz();
2 голосов
/ 30 декабря 2008

Вы можете попробовать - временно - изменить макрос на что-то вроде этого и посмотреть, что не компилируется ...

#define coutError {} if (VERBOSITY_SETTING >= VERBOSITY_ERROR) ods()

Пункты 'else' теперь должны давать ошибки.

1 голос
/ 30 декабря 2008

Я вижу в ваших комментариях выше, что вы думаете об использовании шаблона в макросе, и я пока не могу комментировать (мне не хватает 9 баллов), так что ...

Что мешает вам делать

#define CoutError(s) { if (VERBOSITY_SETTING >= VERBOSITY_ERROR){ ods(s); } }

А потом

void LightSwitch::TurnOn()
{
    if (!PowerToSwitch)
        CoutError("No power!");
    else
        SwitchOn = true;
}

И переопределить шансы для допуска строки или, если нет, просто определить функцию OdsHelper, которая принимает строку и тело которой просто ods << inString? </p>

Я бы не стал играть с макросами, пытаясь имитировать синтаксис <<, если нет четкого усиления. По крайней мере, с макросами, имитирующими синтаксис функции, мы более часто используем и знаем, что должны писать блоки, чтобы избежать странных проблем. </p>

Вам действительно нужен << синтаксис? </p>

А вам действительно нужно ввести шаблон для этого простого поведения?

Да, и последнее - не используйте макросы.

1 голос
/ 30 декабря 2008

Я думаю, что все хорошее использование макроса предшествует '{' или ';'.

Попробуйте это регулярное выражение:

[^{;]\s*coutError

Вам потребуется включить многострочное сопоставление и выполнить поиск по всем файлам.

Возможно, вам понадобится получить больше информации, чтобы найти нужную строку: -)

Альтернативно, изменение макроса - хорошая идея, если мы сможем решить что-то, что не получится правильно. Возможно блок, сопровождаемый условным оператором:

#define coutError {} (VERBOSITY_SETTING >= VERBOSITY_ERROR)?(ods()):(nullstream()) 

(Но требует реализации оператора nullstream ().)

(В качестве альтернативы можно полностью избавиться от условного ответа - как вы предлагаете, это комментарий к другому ответу @Roddy (в настоящее время выбранный ответ)).

p.s. Я знаю, что вы не спрашивали, но простой способ обернуть макрос, чтобы сделать его безопасным, с помощью цикла do {} while(false).

0 голосов
/ 30 декабря 2008

поиск по регулярному выражению?

0 голосов
/ 30 декабря 2008

Я думаю, что реальная проблема заключается в использовании макроса, а не кода, который подвергается предварительной обработке. Но я не думаю, что это ответ, который вы ищете.

Я бы нашел способ сделать это вообще без использования макросов - и если вы используете условные компиляции, вы можете сделать это в вызове ods () - в зависимости от некоторого #define он может использовать любую функциональность, какую пожелаете.

только мои $ .02

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...