Для меня это похоже на ошибку компилятора.Здесь возникают проблемы с разрешением перегрузки и частичным упорядочением функций шаблона.Поскольку обе функции шаблона могут соответствовать списку аргументов (ReadPackager*, bool)
, для выбора более специализированной функции шаблона следует использовать частичное упорядочение функций шаблона.
Проще говоря, функция шаблона, по крайней мере, такая же специализированная, как и другая, еслиаргументы этой функции всегда можно использовать как аргументы другой.
Понятно, что любые два аргумента-указателя соответствуют первой функции Package (), но, например, Package (ReadPackager *, const int *) не может совпадатьвторой.Кажется, это подразумевает, что вторая функция Package является более специализированной и должна разрешать любую неоднозначность.
Однако, поскольку между компиляторами есть разногласия, могут быть некоторые тонкости, которые упускаются из виду в упрощенном объяснении.Поэтому я буду следовать процедуре определения частичного упорядочения шаблона функции из стандарта для определения правильного поведения.
Во-первых, для удобства обозначим функции как P1 и P2.
P1:
template<typename Packager, typename T>
bool Package( Packager* ppkgr, T* pt );
P2:
template<typename Packager>
bool Package( Packager* ppkgr, typename AddPkgrConst<Packager,bool>::type* pb);
Стандарт гласит, что для каждой функции шаблона (T1) мы должны генерировать уникальный уникальный тип для каждого из его параметров шаблона, использовать эти типы для определения вызова функциитипы параметров, а затем используйте эти типы для вывода типов в другом шаблоне (T2).Если это удается, первый шаблон (T1) по меньшей мере так же специализирован, как и второй (T2).Первый P2-> P1
- Синтезировать уникальный тип
U
для параметра шаблона Packager
для P2. - Выполнить вывод типа из списка параметров
P1
.Packager
определяется как U
, а T
определяется как AddPkgrConst<Packager,U>::type
.
Это успешно выполняется, и P1 считается не более специализированным, чем P2.
Теперь P1-> P2:
- Синтезируйте уникальные типы
U1
и U2
для параметров шаблона Packager
и T
для P1, чтобы получить список параметров (U1 *, U2 *). - Выполнить вывод типа из списка параметров
P2
.Packager
выводится как U1. - Для второго параметра вычитание не производится, поскольку, будучи зависимым типом, он считается невыводимым контекстом.
- Следовательно, второй аргумент
AddPkgrConst<U1,bool>::type
, что соответствует bool
.Это не соответствует второму параметру U2
.
Эта процедура завершится неудачно, если мы перейдем к шагу 4. Однако я подозреваю, что компиляторы, которые отклоняют этот код, не выполняют шаг 4 и, следовательно,Рассмотрим P2 не более специализированно, чем P1 только потому, что вывод типа завершился успешноЭто кажется противоречивым, поскольку P1 явно принимает любой вход, который делает P2, а не наоборот.Эта часть стандарта несколько запутанная, поэтому неясно, нужно ли проводить это окончательное сравнение.
Попробуем ответить на этот вопрос, применив §14.8.2.5, абзац 1, Шаблон дедукцииаргументы типа
Аргументы шаблона могут быть выведены в нескольких различных контекстах, но в каждом случае тип, указанный в параметрах шаблона (назовите его P), сравнивается с фактическимtype (назовите его A), и делается попытка найти значения аргумента шаблона (тип для параметра типа, значение для параметра не типового типа или шаблон для параметра шаблона), который будет равен P после заменывыведенные значения (назовите его выведенным A), совместимым с A.
В нашем типе вычетов, выведенный A равен AddPkgrConst<U1,bool>::type
= bool
.Это не совместимо с оригинальным А, который является уникальным типом U2
.Это, кажется, подтверждает позицию, что частичное упорядочение разрешает неоднозначность.