Частичное упорядочение указателя против указателя на константу - PullRequest
0 голосов
/ 18 февраля 2019

Благодаря частичному упорядочению шаблонов функций следующее представляется однозначным:

template <class T> void f(T*) {
   cout << "T*" << endl;
}

template <class T> void f(const T*) {
   cout << "const T*" << endl;
}

int main(){
    int *p = nullptr;
    f(p);
}

T выводится как int в обоих случаях, и обе специализации являются жизнеспособными со вторым требованиемнеявное преобразование квалификации из int * в const int*.Оба добавляются в набор перегрузки.

Чтобы найти наилучшую жизнеспособную функцию, мы переходим к частичному упорядочению.Мы синтезируем новые типы для каждого и получаем void f(X*) и void f(const Y*).Затем мы делаем вывод типа между двумя.[temp.deduct.partial] ¶8:

Используя результирующие типы P и A, затем производится вычет, как описано в 17.8.2.5.(...) Если для данного типа вывод выполняется успешно, считается, что тип из шаблона аргумента, по крайней мере, такой же специализированный, как и тип из шаблона параметра.

Успешен ли вывод для template <class T> void f(T*) дано const Y*?Да, с T=const Y.

Успешен ли вычет для template <class T> void f(const T*) при X*?Да, с T=X (требующим неявного преобразования квалификации).

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

За исключением того, что это не так, так где я ошибся выше?

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Я выяснил, где я ошибся:

Чтобы найти наилучшую жизнеспособную функцию, мы переходим к частичному упорядочению.

Нет, мы не делаем,Чтобы найти наилучшую жизнеспособную функцию, мы пройдемся по шагам в [over.match.best] по порядку.Частичное упорядочение - только одна точка в этом списке, к которой мы фактически никогда не добираемся, потому что наилучшая жизнеспособная функция найдена предыдущим шагом в списке ( для некоторого аргумента j, ICSj (F1) - лучшая последовательность преобразования, чемICSj (F2) ).

Эти две специализации действительно одинаково специализированы, но это не имеет значения, поскольку мы никогда не используем частичное упорядочение.

0 голосов
/ 18 февраля 2019

template <class T> void f(const T*) действительно более специализирован, чем template <class T> void f(T*), но последнее является точным совпадением.

Если вы посмотрите на overload_resolution # best_viable_function :

Лучшая жизнеспособная функция:

1) существует по крайней мере один аргумент F1, неявное преобразование которого лучше, чем соответствующее неявное преобразование для этого аргумента F2
[..]
5) или,если нет, то F1 и F2 являются специализациями шаблонов, а F1 более специализирован в соответствии с правилами частичного упорядочения для специализаций шаблонов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...