#новичкам
Один из способов избежать дублирования кода — использовать макросы. Макросы — инструкции препроцессора, которые позволяют заменять одни строки на другие:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
Теперь вы можете использовать этот макрос, возвращающий максимальное из 2-х значений, для любых типов данных:
int result1 = MAX(1, 2); // Работает
double result2 = MAX(1.5, 2.5); // Тоже работает
Но использование макросов — это игра в русскую рулетку. Никогда не знаешь, когда в голове появится на 2 дырки больше. Они работают на уровне текстовой подстановки, и если что-то пойдет не так, компилятор вам не поможет. Как вы думаете, какие значения будут у переменных result, x и y после выполнения следующего кода?
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int x = 5;
int y = 10;
int result = MAX(++x, ++y);
Мы хотим сравнить две переменные после их инкрементов. Поэтому ожидаемые значения: 11, 6, 11. Однако у препроцессора и компилятора есть свое мнение на этот счет. Реальный вывод:
Result: 12
x: 6
y: 12
Переменная y имеет значение на один больше ожидаемого. Это перестает быть удивительным после того, как мы посмотрим на то, во что раскрывается макрос:
int result = ++x > ++y ? ++x : ++y;
Мы просто подставили текст и в любых значениях x и y, одна из этих переменных претерпит лишний инкремент.
Более сложные ситуации генерируют все менее и менее тривиальные ошибки.
Недостатки макросов
🔞 Нетипобезопасность: Макросы не проверяют типы данных. Программа может скомпилироваться, но упасть в runtime.
🔞 Побочные эффекты: Макросы могут привести к неожиданным результатам, особенно если аргументы содержат побочные эффекты (например, инкременты).
🔞 Сложность отладки: Макросы могут раскрываться в причудливые строки, которые вы просто не увидите в своем коде. Придется отлаживаться по файлу с кодом после препроцессора, а это нетривиальная задача.
Макросы — это как использовать переводчик текста по изображению. В идеальных случаях работает хорошо, но иногда может "кабачок" интерпретировать как "маленький дешевый ресторан".
Поэтому CppCoreGuideLines говорят нам не использовать макросы при определении функций.
Вместо макросов в С++ есть шаблоны и вычисления времени компиляции, возможности которых с каждым стандартом все возрастают.
Don't be confusing. Stay cool.
#cppcore