C 20 range-v3 и адаптер zip_with view

#c #c 20 #range-v3

#c #c 20 #диапазон-v3

Вопрос:

С помощью такого отложенного комбинатора диапазонов, как ranges::view::reverse я могу либо предоставить ему один аргумент (например reverse(iota(0,3)) ); или я могу использовать его для адаптации диапазона с помощью operator| (например iota(0,3) | reverse ). Эта четность выглядит довольно регулярно; ниже приведены примеры нулевых, унарных и двоичных представлений:

 #include <range/v3/all.hpp>
#include <iostream>

int main(int argc, char *argv[])
{
  using namespace ranges::view;
  std::cout <<        (iota(0,9) | reverse)      << ' ';
  std::cout << reverse(iota(0,9))                << 'n';

  std::cout <<        (iota(0,9) | chunk(4))     << ' ';
  std::cout <<   chunk(iota(0,9),4)              << 'n';

  std::cout <<        (iota(0,9) | replace(5,0)) << ' ';
  std::cout << replace(iota(0,9),5,0)            << 'n';
  return 0;
}
  

Однако я замечаю, что ranges::view::zip_with комбинатор может использоваться только во второй (безадаптерной) форме; например zip_with(std::plus{},iota(0,9),iota(0,9)) . Есть ли техническая причина, по которой zip_with невозможно определить для работы с operator| ? Существует ли канонический порядок аргументов комбинаторов отложенного диапазона в библиотеке ranges-v3?

Я работаю с последней версией (v0.4.0) библиотеки ranges-v3.

Комментарии:

1. Как бы вы преобразовали два диапазона в один zip_view ?

2. Вы бы просто передали один из них.

Ответ №1:

Это довольно распространенное соглашение в range-v3, которое r | adapter(x) означает то же самое, что и adapter(r, x) . (Действительно, есть даже язык программирования Elixir, для которого r |> adapter(x) фактически выполняется прямая оценка as adapter(r, x) ).

Проблема с zip_with заключается в том, что использование, как вы указываете, является:

 zip_with(std::plus{},iota(0,9),iota(0,9))
  

Что означает, что логическое разделение с operator| было бы:

 std::plus{} | zip_with(iota(0,9),iota(0,9))
  

Но тогда это не диапазон с левой стороны. Это какой-то двоичный оператор. range-v3 предназначен для объединения в цепочки диапазонов. В любом другом случае это диапазон, который отображается с левой стороны | . Так что, хотя технически это не сложно сделать, это кажется чем-то существенно иным.

Комментарии:

1. Вы также столкнетесь с проблемами, если ваш первый диапазон также доступен для вызова, потому что теперь у вас есть zip_with(deduced_potentially_callable, deduced_range) в rhs

2. Спасибо за вклад @Barry. В этом случае zip_with можно было бы просто определить, чтобы его функция принимала аргумент последней; т.е. zip_with(iota(0,9),iota(0,9),std::plus{}) .

3. @user2023370 Да, но (а) zip_with принимает различное количество диапазонов, поэтому функция вроде как должна запускаться первой, и (б) из других языков известно, что функция запускается первой (например, Haskell ).

4. Так что, может быть, соглашение должно быть таким, что r | adapter(x) означает то же самое, что и adapter(x,r) ?