Поиск шаблона оператора в файле C++

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

#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 < <...; else ", чтобы выяснить, есть ли другие случаи, когда это происходит, чтобы убедиться, что при исправлении макроса он действительно будет работать правильно.

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
329
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

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

только мои 0,02 доллара

я собирался исправить это с помощью шаблона, так что: typedef ods <VERBOSITY_ERROR> coutError;

FryGuy 30.12.2008 00:29

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

Что ж, проблема в том, что содержимое if может быть сложным, и операторы после coutError тоже могут быть сложными. Какое регулярное выражение можно использовать?

FryGuy 30.12.2008 00:28
Ответ принят как подходящий

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

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

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

хорошо, но я думаю, что у него также могут быть проблемы с if, у которых нет elses? Хотя не уверен.

Tim 30.12.2008 00:40

Это хорошая идея, но я не думаю, что ваша линия вызовет нужные проблемы. else будет по-прежнему присоединяться к оператору #defined if.

Douglas Leeder 30.12.2008 00:41

Думаю, вот что нужно: #define coutError {} ods ()

FryGuy 30.12.2008 00:49

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

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

[^{;]\s*coutError

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

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

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

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

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

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

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

Я не думаю, что вы можете обернуть этот конкретный макрос во что-нибудь и избавить его от этой проблемы. Это также отлавливает некоторые ложные срабатывания в этом "if (...) coutError <<" ... "; someotherstatement;" макрос не влияет на него, но это регулярное выражение его поймает.

FryGuy 30.12.2008 00:54

Regex find = new Regex (@ "if [^ {};] + coutAgent [^ {};] +; [^ {};] + else", RegexOptions.Singleline); кажется, трюк

FryGuy 30.12.2008 00:54

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

Что тебе мешает

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

А потом

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

И переопределите ods, чтобы принять строку, или, если вы не можете, просто определите функцию OdsHelper, которая принимает строку и тело которой просто ods << inString?

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

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

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

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

Проблема больше в том, что он имитирует cout. Например: coutError << "Ошибка чтения:" << powerSetting << endl; И код не мой, это просто часть фреймворка, который мы используем там, где я работаю. Я согласен с тем, что макросы - это зло. Собственно, это то, что я цитирую, когда спорим :)

FryGuy 30.12.2008 01:09

Отлично, теперь я могу прокомментировать :) Вы должны попытаться реорганизовать фреймворк, удалив хотя бы более проблемные макросы и попытаться установить для них стандарты. Распространенным стандартом является то, что макросы находятся в блоках. Расскажите об этом своей команде и попытайтесь убедить их. Если не можете, значит, вы застряли :)

Daniel Daranas 30.12.2008 02:24

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

#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();

Это отличное исправление; даже проще, чем тот, который я собирался сделать. Тем не менее, основной смысл вопроса заключался в том, чтобы выяснить, появятся ли какие-либо ошибки, исправив проблему.

FryGuy 30.12.2008 02:20

Другие вопросы по теме