Ваша специализация не используется в разрешении перегрузки. Разрешение перегрузки синтезирует только сигнатуру из шаблона primary . Специализация используется только тогда, когда вызывает функцию, и только если сигнатура совпадает с сигнатурой, которую компилятор сам синтезировал. Поскольку первичный параметр принимает аргумент по значению, это сигнатура, которая участвует в разрешении перегрузки:
void print(Foo); // T = Foo
И она не соответствует подписи, которую вы указали в специализации (T = Foo const&
), поэтому специализацияне называется. Фактически, единственный способ вызвать вашу специализацию, как есть, - это явно указать аргумент шаблона:
print<Foo const&>(foo);
Чтобы продолжить, нужно не специализироваться, а перегрузить. Это можно сделать, просто удалив интродьюсер template<>
. Обычная перегрузка участвует в разрешении перегрузки и будет выбираться из сгенерированного шаблона.