Используйте встроенные шаблоны функций вместо параметризированных макросов
Приведенный ранее пример:
#define SQUARE(x) ((x) * (x))
где:
SQUARE(++x)
расширяется до:
((++x)*(++x))
инкрементируя x
дважды. Вы не можете решить эту проблему в Си, а в Си++ можете. Простая встроенная функция работает вполне удовлетворительно, в таком виде:
inline int square( int x ){ return x * x; }
не давая побочного эффекта. Тем не менее, она допускает лишь целочисленные аргументы. Шаблон функции, который расширяется во множество перегруженных встроенных функций, является более общим решением:
template class type
inline type square( type x ){ return x * x; }
К несчастью, это срабатывает только в простых ситуациях. Следующий шаблон не может обработать вызов max(10, 10L), потому что не совпадают типы аргументов:
template class type
inline type max( type x, type y ){ return (x y) ? x : y; }
Для обработки max(10, 10L) вы должны использовать прототип, чтобы принудить к расширению по тому варианту max(), который может выполнить данную работу:
long max( long, long );
Прототип вызывает расширение шаблона. Компилятор с легкостью преобразует аргумент типа int в long, даже если ему не нужно делать это преобразование для расширения шаблона.
Заметьте, что я здесь рекомендую использование шаблонов только потому, что square
является встроенной функцией. Если бы этого не было, то для того, чтобы такой механизм был жизнеспособным, пришлось бы генерировать слишком много кода.