Разве rvalue ссылка не смешивает тип и категорию? - PullRequest
0 голосов
/ 25 мая 2019

Этот пост отражает мой текущий уровень понимания категории стоимости.

Значение категории является свойством выражения. Тип является пропетрией переменной.

Допустим, у нас есть следующее объявление:

int x;

Что такое х? Это переменная и это выражение.

Написание нового синтаксиса, такого как:

int&& ref

вместо

int& ref

заставляет людей думать, что мы сделали что-то, связанное с типами, но на самом деле мы сделали что-то, связанное с выражениями, а не с типами. (Мы указали, какие выражения могут быть связаны с этими переменными.)

Вероятно, различие между "временными" и "невременными" может быть сделано другим способом, может быть, что-то вроде этого:

void func(int&); // for "non-temporaries"
void func((int&)); // for "temporaries

или как-то иначе, но не возиться с типами.

Итак, мой вопрос: Нужно ли кодировать информацию о категории выражений в синтаксис для типов? Каковы были причины этого дизайнерского решения?

1 Ответ

2 голосов
/ 25 мая 2019

Rvalue-ссылки - это отличный тип от lvalue-ссылок, так что они могут что-то кодировать: конкретное намерение пользователя при создании этой ссылки.Если вы сделаете ссылку на rvalue, вы определенно намереваетесь перенести объект, на который она ссылаетсяЭто отдельное намерение от использования ссылки на lvalue.

Это конкретное намерение не может быть обнаружено только при использовании имени;категория значения ссылочной переменной rvalue - lvalue.Но это намерение обнаруживается по типу .И тип имеет значение.

Мы хотим иметь возможность перегружать функции с этим объявленным намерением, иметь одну перегрузку, которая может принимать объект, который может быть перемещен, а другую - нет.Это основа различия между конструктором копирования и конструктором перемещения.C ++ перегружает функции на основе типов, поэтому ... мы должны указать это намерение на уровне типа.

В вашем примере func, если int& и (int&) имеют одинаковый тип, то с помощьюправила C ++ в том виде, в каком они существуют в настоящее время, обе эти func функции объявляют одну и ту же функцию .Поэтому вам нужно придумать новые правила, которые определяют концепцию «сигнатуры функции» как нечто большее, чем просто задействованные типы.Вам придется возиться с разрешением перегрузки, чтобы определить, какая функция вызывается.И т. Д.

Плюс, std::move работает (то есть возвращаемое значение может связываться со ссылками rvalue), поскольку категория значений возвращаемого значения ссылочного типа rvalue определена как xvalue.И xvalues ​​может связываться с rvalue ссылками.С вашей точки зрения, этот (&) синтаксис должен иметь аналогичные свойства.Но он не может быть основан на типе, потому что по определению он не меняет тип.Таким образом, по сути, вы должны объявить, что ссылочные типы могут иметь эту дополнительную, нетиповую информацию, расположенную рядом с типом.Эта информация не может быть запрошена каким-либо обычным интерфейсом, в отличие от информации о типе для выражения, которая может быть запрошена с помощью decltype.

. Или вы можете просто создать новый тип и получить большую часть этого бесплатно.Вам все еще нужно изучить, как работает разрешение перегрузки для этого нового типа, и вам все еще нужно определить правила привязки ссылки rvalue, но концепция сигнатуры функции не изменилась, и вам не нужен этот неуклюжий дополнительный канал информации, который находится рядомтип.

Использование ссылки для этого намерения также допускает правила свертывания ссылок, которые являются основой "идеальной" пересылки: возможность написать одну (шаблонную) функцию, которая пересылает выражения любогокатегория значения для пункта назначения таким образом, что остается неизменным, может ли пункт назначения копировать / перемещать их.

...