#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)
в rhs2. Спасибо за вклад @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)
?