Частичное упорядочение с L-значением-ref
Почему это неоднозначно?
template<class T> void g(T) {} // 1
template<class T> void g(T&) {} // 2
int main() {
int q;
g(q);
}
Я понимаю, что это частичный порядок контекста. И мое, возможно, ошибочное мышление: любой T& from #2 может быть помещен в #1, но не любой T из # 1 является законным в #2. Так что частичное упорядочение должно работать.
2 ответа
ХОРОШО. Я думаю, это то, что вы ищете. Не вдаваясь в двойное применение сравнения параметров с типами аргументов, в стандарте выпало следующее:
C++ 11 §14.8.2.4p5
Перед выполнением частичного упорядочения выполняются определенные преобразования для типов, используемых для частичного упорядочения:
- Если P является ссылочным типом, P заменяется указанным типом.
- Если A является ссылочным типом, A заменяется указанным типом.
C++ 11 §14.8.2.4p6 продолжает говорить о том, что происходит, когда оба являются ссылочными типами, но это здесь не применимо (хотя и интересное чтение). в твоем случае только один есть, поэтому его раздевают. Оттуда:
C++ 11 §14.8.2.4p7
Удалите все cv-квалификаторы верхнего уровня:
- Если P является cv-квалифицированным типом, P заменяется cv-неквалифицированной версией P.
- Если A является cv-квалифицированным типом, A заменяется cv-неквалифицированной версией A.
Теперь оба абсолютно равны, и, таким образом, у вас есть двусмысленность, которая, я считаю, подтверждена в C++11 §14.8.2.4p10. Текст C++11 §14.8.2.4p9 охватывает оба ссылочных типа, что, опять же, здесь не так:
C++ 11 §14.8.2.4p10
Если для каждого рассматриваемого типа данный шаблон, по крайней мере, столь же специализирован для всех типов и более специализирован для некоторого набора типов, а другой шаблон не более специализирован для каких-либо типов или, по крайней мере, не так специализирован для любых типов, то данный Шаблон более специализирован, чем другой шаблон. В противном случае ни один шаблон не является более специализированным, чем другой.
Но чтение стандарта в этом разделе для меня все равно, что расшифровать греческий язык, так что я могу быть далеко от базы. (без обид грекам =P).
Это, однако, заставило меня думать " const T&
против T
с учетом того же условия вызова g(q)
, также должен быть неоднозначным, если все, что я только что прочитал, применяется как написано."Конечно, я попробовал это, и та же самая неоднозначность была отмечена.
Ваши рассуждения верны, когда эти два типа конкурируют в частичном порядке частичных специализаций шаблона класса, и именно так все и работает.
Но когда ссылочный тип сравнивается с нереференсным типом, общая суть в том, что они неоднозначны в сценарии вызова, если ничто иное не делает один предпочтительным по сравнению с другим. То есть тип ссылки на тип ссылки не имеет значения в разрешении перегрузки по сравнению с другими, поэтому частичное упорядочение также не учитывает это.