#c #macros #c-preprocessor
#c #макросы #c-препроцессор
Вопрос:
В чем лучше всего скрывать оператор if #define
?
- Вы можете использовать
if
в define:
#define MY_MACRO(isTrue) if(isTrue) do()
Моя интуиция говорит, что это плохой подход. Не могли бы вы привести пример, почему это так или почему нет? Например, любой, кто использует это, может добавить else
после макроса.
- Вы можете использовать тернарный оператор:
#define MY_MACRO(isTrue) (isTrue) ? do() : do_not()
//OR
#define MY_MACRO(isTrue) (isTrue) ? do() : (void)0
Здесь я понимаю, почему это нехорошо. Например, любой может вызвать вашу функцию do()
с помощью простого true || MY_MACRO(?)
- Мое текущее решение этой проблемы — do-while-false
#define MY_MACRO(isTrue) do { if(isTrue) do(); } while (false)
Действительно ли это лучший подход? Что плохого может случиться с этим макрокомандой?
Комментарии:
1. Зачем вам нужно его усложнять?
2. Я предполагаю, что
do()
предполагается, что это функция, а не использованиеdo
ключевого слова, верно?3. Какова наилучшая практика скрытия оператора if в #define — лучшая практика — не делать этого.
4. «любой может вызвать вашу функцию
do()
с помощью » -> Ничто из этого не помешает кому-либо вызватьdo()
функцию.
Ответ №1:
Для 1 его нельзя использовать таким образом:
if (foo) MY_MACRO(bar);
else something_else();
Потому что это было бы расширено следующим образом:
if (foo) {
if (isTrue) {
do();
} else {
something_else();
}
}
else
Будет (неожиданно) else
для if
внутри макроса.
Плохая особенность вашего текущего подхода заключается в том, что его нельзя использовать там, где требуется оператор (например, f((MY_MACRO(a), b), c)
в выражении через запятую не будет работать), но поскольку вы используете его для побочных эффектов do()
, он не будет использоваться там, где требуется оператор.
Поскольку он кажется довольно коротким, вы можете заставить его действовать как оператор, просто добавьте еще одну пару скобок, чтобы решить вашу проблему с помощью 2:
#define MY_MACRO(isTrue) ((isTrue) ? do() : (void)0)
Вы также должны захотеть рассмотреть static conditional_do(bool isTrue) { if (isTrue) { do(); } }
вместо макроса.