Неклассовые значения всегда имеют cv-неквалифицированные типы
В разделе 9.10 раздела 9 говорится, что "неклассические значения всегда имеют cv-неквалифицированные типы". Это заставило меня задуматься...
int foo()
{
return 5;
}
const int bar()
{
return 5;
}
void pass_int(int&& i)
{
std::cout << "rvalue\n";
}
void pass_int(const int&& i)
{
std::cout << "const rvalue\n";
}
int main()
{
pass_int(foo()); // prints "rvalue"
pass_int(bar()); // prints "const rvalue"
}
В соответствии со стандартом, нет такой вещи, как константа rvalue для неклассических типов, но bar()
предпочитает привязываться к const int&&
. Является ли это ошибкой компилятора?
EDIT: По-видимому, this
также является константой:)
EDIT: эта проблема, похоже, исправлена в g++ 4.5.0, обе строки печатают "rvalue" сейчас.
Ответы
Ответ 1
Комитет уже, похоже, осознает, что в этой части стандарта есть проблема. CWG issue 690 рассказывает о некоторой схожей проблеме с точно такой же частью стандарта (в "дополнительной заметке" от сентября 2009 года). Я предполагаю, что новый язык будет подготовлен для этой части стандарта в ближайшее время.
Изменить: я только что отправил сообщение на comp.std.С++, отметив проблему и предложив новую формулировку для соответствующей части стандарта. К сожалению, будучи модерируемой новостной группой, почти все, вероятно, забудут этот вопрос к тому моменту, когда он сделает это через очередь утверждения там.
Ответ 2
Хорошая точка. Я думаю, есть две вещи, на которые нужно обратить внимание: 1) как вы указали неклассическое значение rvalue и 2) как работает разрешение перегрузки:
Критерии отбора для лучших функция - количество аргументов, насколько аргументы соответствуют list-type-list кандидата функция, [...]
Я не видел ничего в стандарте, который говорит мне, что неклассовые значения r обрабатываются специально во время разрешения перегрузки.
Ваш вопрос рассмотрен в проекте стандарта, который у меня есть (N-4411):
Однако вступление в игру - это параллельное чтение ссылочного связывания, неявных последовательностей преобразования, ссылок и разрешения перегрузки в целом:
13.3.3.1.4 Связывание ссылок
2 Когда параметр ссылочного типа не связано непосредственно с аргументом выражение, последовательность преобразования это тот, который требуется для преобразования выражения аргумента в базовый тип ссылки согласно до 13.3.3.1.
и
13.3.3.2 Ранжирование неявных последовательностей преобразования
3 Две неявные последовательности преобразования одна и та же форма неразличима последовательности преобразований, если один из применяются следующие правила:
- Стандартная последовательность преобразования S1 является лучшей последовательностью преобразования, чем стандарт
последовательность преобразования S2, если
- S1 и S2 являются ссылочными привязками (8.5.3), и ни одна из них не относится к неявный параметр объекта нестатический функция-член, объявленная без ref-квалификатора, и либо S1 связывает Ссылка на lvalue к lvalue и S2 связывает ссылку rvalue или S1 связывает значение rvalue ссылка на rvalue и S2 связывает ссылку lvalue.
[Пример:
int i;
int f();
int g(const int&);
int g(const int&&);
int j = g(i); // calls g(const int&)
int k = g(f()); // calls g(const int&&)