Неклассовые значения всегда имеют cv-неквалифицированные типы
§3.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"
}
В соответствии со стандартом не существует такого понятия, как постоянное значение для неклассовых типов, однако bar()
предпочитает связываться с const int&&
, Это ошибка компилятора?
РЕДАКТИРОВАТЬ: видимо, this
это также постоянное значение:)
РЕДАКТИРОВАТЬ: Эта проблема, кажется, исправлена в g++ 4.5.0, обе строки теперь выводят "rvalue".
2 ответа
Комитет, похоже, уже знает, что в этой части стандарта есть проблема. В выпуске CWG 690 говорится о несколько схожей проблеме с точно такой же частью стандарта (в "Дополнительной заметке" от сентября 2009 г.). Я предполагаю, что новый язык будет разработан для этой части стандарта в ближайшее время.
Изменить: я только что отправил сообщение на comp.std.C++, отмечая проблему и предлагая новую формулировку для соответствующей части стандарта. К сожалению, будучи модерируемой группой новостей, почти все, вероятно, забудут этот вопрос к тому времени, когда он пройдет через очередь утверждения там.
Хорошая точка зрения. Я думаю, есть две вещи, на которые стоит обратить внимание: 1) как вы указали на неклассовое rvalue thingy и 2) как работает разрешение перегрузки:
Критериями выбора наилучшей функции являются количество аргументов, насколько хорошо аргументы соответствуют списку параметров-типов функции-кандидата, [...]
Я не видел ничего в стандарте, который говорит мне, что не-классные значения обрабатываются специально во время разрешения перегрузки.
Ваш вопрос описан в проекте стандарта, который у меня есть (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&&)