Во-первых, последовательность преобразования всех трех одинакова, за исключением того, что для первых двух есть преобразование lvalue (преобразование lvalue в rvalue), которое, однако, не используется при упорядочении последовательностей преобразования.Все три являются точными совпадениями (специализация шаблона функции имеет тип параметра char const(&)[2]
).
Если вы перебираете правила на 13.3.3.2p3
, вы останавливаетесь на этом абзаце
S1 и S2 являются ссылочными привязками (8.5.3), и ни одна из них не ссылается на неявный параметр объектанестатической функции-члена, объявленной без квалификатора ref, и S1 связывает ссылку rvalue с rvalue, а S2 связывает ссылку lvalue.
Последовательность преобразования не может быть сформирована, если для нее требуется привязкаrvalue ссылка на lvalue, спецификация говорит в 13.3.3.1.4p3.Если вы посмотрите, как работает привязка ссылок в последнем пуле 8.5.3p5, то из массива lvalue будет создано временное (я думаю, что они имели в виду rvalue временный) типа char const*
и будет привязана ссылка на этот временный,Поэтому я думаю, что (1)
лучше, чем (2)
.То же самое относится к (1)
против (3)
, хотя нам это не понадобится, потому что (3)
- это шаблон, поэтому в ничьей мы бы снова выбрали (1)
.
В n3225
они изменили правила привязки ссылок, чтобы ссылки rvalue могли связываться с выражениями инициализатора, которые являются lvalue, при условии, что ссылка будет связана с rvalue (возможно, созданным путем преобразования инициализатора должным образом до того, как).Это может повлиять на обработку Visual C ++, который может быть не актуален здесь.
Я не уверен насчет лязга.Даже если он проигнорирует (1)
, он окажется в связке между (2)
и (3)
и должен будет выбрать (2)
, потому что это не шаблон.
Я думаю, что последний пункт 8.5.3p5 сбивает с толку, потому что он говорит: «В противном случае временный тип ..».Неясно, рассматривается ли временное значение как lvalue или как rvalue в 13.3.3.1.4p3, что означает, что я не уверен, как на самом деле должно вести себя следующее в соответствии с точными словами спецификации
void f(int &);
void f(int &&);
int main() {
int n = 0;
f(n);
}
Если мы предположим, что временное значение рассматривается как r-значение в соответствии с пунктом 13, то мы привязываем r-значение ref к r-значению во второй функции и l-значению в первой.Поэтому мы выберем вторую функцию, а затем получим диагностику по последнему пункту 8.5.3p5, потому что T1
и T2
связаны со ссылками.Если мы предположим, что временное значение рассматривается как lvalue согласно пункту 13, то следующее не будет работать
void f(int &&);
int main() {
f(0);
}
, поскольку мы привязываем rvalue ref к lvalue, что в соответствии с пунктом 13 сделает функцию нежизнеспособной,И если мы интерпретируем «привязка rvalue ref к lvalue» для ссылки на выражение инициализатора вместо конечного выражения, связанного с, мы не примем следующее
void f(float &&);
int main() {
int n = 0;
f(n);
}
Это, однако, действительно с n3225,Так что, похоже, есть некоторая путаница - я отправил ДР в комитет по этому поводу.