Почему разрешение перегрузки выбирает vval * версию eval вместо ... версии для 0
Поскольку 0 является константой нулевого указателя.
но не для 1?
Поскольку 1 не является константой нулевого указателя.
Стандартное правило:
[conv.ptr]
Константа нулевого указателя - это целочисленный литерал ([lex.icon]) со значением ноль или значением типа std :: nullptr_t. Константа нулевого указателя может быть преобразована в тип указателя; результатом является значение нулевого указателя этого типа ...
Кажется, что в обоих случаях это может означать, что аргумент является целым и принимает переменную c версия.
Аргумент C -style variadi c является наименее предпочтительным выбором по разрешению перегрузки, даже если для него не требуется преобразование типа аргумента, которое потребуется другому кандидату. Пока есть любой другой действительный кандидат, другой кандидат выбран. В этом случае существует перегрузка void*
, которая действительна для 0, но не для 1.
Если у вас была перегрузка eval(int)
, она будет выбрана как для 0, так и для 1.
PS Это свойство разрешения перегрузки аргументов C -style variadi c иногда используется для реализации черт типа магами темных шаблонов.