Что означают адаптеры диапазона default_constructible в C ++ 23?

Начиная с C++23, s больше не требуется. Для адаптеров диапазона, таких как views::filter и views::transform, их конструктор по умолчанию переопределяется как:

      template<input_­range V, indirect_­unary_­predicate<iterator_t<V>> Pred>
  requires view<V> && is_object_v<Pred>
class filter_view : public view_interface<filter_view<V, Pred>> {
private:
  V base_ = V();                              // exposition only
  copyable-box<Pred> pred_;                   // exposition only
public:
  filter_view() requires default_­initializable<V> && default_­initializable<Pred> = default;
};

И поскольку конструктор по умолчанию для ref_viewбыл удален в p2325r3 , это означает, что адаптеры диапазона применены к lvalue rangeтакие как std::vectorбольше нет :

      std::vector v{1, 2, 3};
auto r = v | std::views::filter([](auto) { return true; });
decltype(r){}; // ok in C++20, error in C++23

Только когда адаптеры диапазона применяются в таких s, как std::string_view или views::iota(0), возвращенные представления могут быть:

      auto r = std::views::iota(0) | std::views::filter([](auto) { return true; });
decltype(r){}; // ok in C++20 and C++23

Но что касается этих случаев, я действительно не могу придумать варианты использования, чтобы сделать их, даже если это возможно. Если мы создаем по умолчанию, это означает, что мы создаем пустой, и, очевидно, бессмысленно применять адаптеры диапазона к пустому s:

      constexpr auto r = std::views::iota(0, 10)
                 | std::views::transform([](auto x) { return x; });
static_assert(!std::ranges::empty(r));
// views::iota is default-constructible, so r is also default-constructible
static_assert( std::ranges::empty(decltype(r){}));

На мой взгляд, конструктор по умолчанию для адаптеров диапазона в C++20 просто удовлетворяет требованиям, поскольку view больше не требуется, чтобы быть в C++23, нет необходимости в конструкторах по умолчанию этих адаптеров для существующих.

Почему конструктор по умолчанию для этих адаптеров диапазона не удаляется в C++23, а превращается в функцию ограничения? Действительно ли есть дело, которое требует, чтобы это было default_constructible? Какие соображения стоят за этим?

1 ответ

Решение

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

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

Если ты transformв представлении, которое является конструктивным по умолчанию (и предположительно V является конструктивным по умолчанию таким образом, чтобы иметь осмысленное состояние, что не является недопустимым: построенный по умолчанию string_view является допустимым пустым диапазоном) и ваша функция F также является конструктивным по умолчанию (как, скажем, любая лямбда без захвата находится в C ++ 20), тогда transform_view<V, F>действительно также должен быть конструктивным по умолчанию. На самом деле нет особых причин для того, чтобы этого не было, фактически условно предоставить этот конструктор можно бесплатно, и он не может причинить вред.

Таким образом , между не предоставляя конструктор по умолчанию и условно обеспечивая конструктор по умолчанию , в котором было бы разумно сделать так, последний просто кажется более удобным для пользователя выбора.

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


Обратите внимание, что это не новая функция библиотеки для C++23, а, скорее, недостаток C++20.

Другие вопросы по тегам