Подтвердить что ты не робот

Почему std:: sort не принимает компаратор по ссылке?

standard на std:: reference_wrapper объясняет, что std::sort теперь принимает std::reference_wrapper, что позволяет передавать компаратор по ссылке.

Есть ли причина, по которой std::sort не принимала компаратор по ссылке в первую очередь?

4b9b3361

Ответ 1

Короче говоря, не нужно было брать его по ссылке; это означает решение "по дизайну".

Я полагаю, что рассуждения сосредотачиваются вокруг нескольких основ, которые существовали на С++ и стандартной библиотеке в течение длительного времени;

  • Сеантика значений
  • Наложение как можно меньше ограничений на реализацию

Семантика значения можно увидеть почти везде. Почти все алгоритмы, контейнеры и т.д. Ожидают, что содержащиеся в них данные будут подчиняться нормальным правилам значений, т.е. Ведут себя так, как если бы они были встроенными. Это одна из причин, лежащих в основе системы типа С++, чтобы позволить пользовательским типам вести себя так, как если бы они были встроенными типами.

Реализация алгоритма (ов) может свободно копировать аргументы функции по мере необходимости. Ограничение подписи на ссылку, когда реализация позволяет копировать функтор вокруг, не очень полезна; поэтому просто разрешите копию с самого начала. Это означает, что объекты функции не должны содержать какое-либо состояние, оно может не сохраниться; в свою очередь это эффективно делает функторы очень легкими, и в любом случае нет причин для ссылки.

25.1/10 Библиотека алгоритмов (проект С++ n3797)

[Примечание. Если не указано иное, алгоритмы, которые принимают функциональные объекты в качестве аргументов, могут свободно копировать эти функциональные объекты. Программисты, для которых важна идентичность объекта, должны рассмотреть возможность использования класса-оболочки, который указывает на объект не поддающейся обработке объекта, такой как reference_wrapper (20.9.3) или какое-то эквивалентное решение. -end note]

Общее примечание по дизайну API. Дизайн API для спецификаций и стандартов, особенно с помощью шаблонов, является нетривиальной задачей в лучшие времена. Будет ли комитет сегодня разрабатывать функцию по-разному с значениями r, сглаживанием ссылок, совершенной пересылкой и перемещением семантики? Я не знаю. На мой взгляд, использование объекта функции по значению уравновешивает проблемы, связанные с внутренними копиями и ходами, возможными оптимизациями и привязкой к временным объектам (pr-values ​​/x-values). "Универсальная ссылка" здесь, возможно, была лучше, но мне кажется, что устаревший аргумент перевешивает аргумент в пользу этого изменения.

Ответ 2

В С++ 03 принятие компаратора по ссылке предотвратит привязку к значению const r, например. выражение указателя функции:

bool comp(T const&, T const&);
sort(first, last, &comp);

Или временный функтор:

struct Comparator { bool operator()(T const&, T const&) { ... } };
sort(first, last, Comparator());

В С++ 11, взяв компаратор по универсальной ссылке, вы избежите этой проблемы, но это ненужное изменение, потому что у нас есть reference_wrapper.