Перегрузка и специализация. Тонкий момент

В сегодняшней краткой заметке я опишу тонкий момент связанный с перегрузкой и специализацией функций. Не так давно встретилось на практике и появился повод проапдейтить запись в личной БД на эту тему. Этой информацией и поделюсь.Пример template void foo (T); // 1 template<> void foo (int*); // 2 template void foo (T*); // 3

template void bar (T); // 4 template void bar (T*); // 5 template<> void bar (int*); // 6

void f () { int i; foo (&i); bar (&i); } Итак у нас есть 2 абсолютно одинаковых набора функций, однако, как вы понимаете, без подвоха тут не обойдется. Какие именно из них будут вызваны? Объяснение Те кто ответил 3 и 6 могут сегодня потратить на торчание на хабре на полчаса больше рабочего времени чем обычно. Чтобы объяснить такое поведение нужно вспомнить какие существуют категории функций с точки зрения перегрузки.1. Обычные функции;2. базовые шаблоны. Это функции вида

template void bar (T); 3. Специализации шаблонов функций.Поведение компилятора для разрешения перегрузки между этими тремя категориями вполне ожидаемо. Сначала выбирается лучший кандидат среди обычных функций и базовых шаблонов, причем предпочтение отдается обычным функциям. Если же более подходящим является базовый шаблон, то проверяется, а нет ли у него еще более подходящих специализаций и, если есть, выбирается одна из них.

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

То есть в примере выше (2) является специализацией не (3), а (1), поэтому для перегрузки будет выбран более подходящий базовый шаблон (3). Во втором же случае (6) является специализацией (5), которая в свою очередь является лучшей кандидатурой, чем (4).

© Habrahabr.ru