Возвращать различные конструкции диапазона из функции
Я пытаюсь получить диапазон просмотра, который ведет себя как истинно-ложные маски. Чтобы делать логические операции, я хочу реализовать и и, и / или маски. У меня есть рабочее время компиляции или:
struct make_or_mask_fn
{
template<typename... Msks>
auto operator()(Msks&&... msks) const
{
CONCEPT_ASSERT((Range<Msks>() || ...));
return ranges::view::zip(std::forward<Msks>(msks)...) |
ranges::view::transform(
[](auto&& range_item) -> bool {
return tuple_or(range_item);
});
}
private:
template<typename... T>
static bool variable_length_or(const T... v)
{
return (v || ...);
}
template<typename... T, std::size_t... Idx>
static bool tuple_or(const std::tuple<T...> t,
std::index_sequence<Idx...>)
{
return variable_length_or(std::get<Idx>(t)...);
}
template<typename... T>
static bool tuple_or(const std::tuple<T...> t)
{
return tuple_or(t, std::index_sequence_for<T...>{});
}
};
RANGES_INLINE_VARIABLE(make_or_mask_fn, make_or_masker)
который я могу назвать просто отлично
std::vector<bool> mask1 = ...
std::vector<bool> mask2 = ...
std::vector<bool> mask3 = ...
auto or_of_masks = make_or_masker(mask1, mask2, mask3);
Чего не может сделать в данный момент, так это создать или из нескольких масок, которые неизвестны во время компиляции. Моя текущая попытка состоит в том, чтобы принять vector
диапазонов, проверьте его размер, а затем вызовите шаблон переменной или ранее:
struct make_vector_or_mask_fn
{
template<typename Msk>
auto operator()(std::vector<Msk> msks)
const // TODO const and reference types
{
CONCEPT_ASSERT(Range<Msk>());
// todo return range with all true (an or of zero elements is true)
assert(msks.size() != 0);
if(msks.size() == 1)
return or_ranges(msks[0]);
if(msks.size() == 2)
return or_ranges(msks[0], msks[1]);
if(msks.size() == 3)
return or_ranges(msks[0], msks[1], msks[2]);
/// TODO: go until ... maybe 8 and recurse afterwards
}
private:
template<typename... Msks>
static auto or_ranges(Msks&&... msks)
{
CONCEPT_ASSERT((Range<Msks>() || ...));
return ranges::view::zip(std::forward<Msks>(msks)...) |
ranges::view::transform(
[](auto&& range_item) -> bool {
return tuple_or(range_item);
});
}
template<typename... T>
static bool variable_length_or(const T... v)
{
return (v || ...);
}
template<typename... T, std::size_t... Idx>
static bool tuple_or(const std::tuple<T...> t,
std::index_sequence<Idx...>)
{
return variable_length_or(std::get<Idx>(t)...);
}
template<typename... T>
static bool tuple_or(const std::tuple<T...> t)
{
return tuple_or(t, std::index_sequence_for<T...>{});
}
};
RANGES_INLINE_VARIABLE(make_vector_or_mask_fn, make_vector_or_masker)
Это не компилируется со следующей ошибкой:
../include/range/v3/view/mask.hpp:221:25: error: 'auto' in return type deduced as 'ranges::v3::transform_view<ranges::v3::zip_view<ranges::v3::iterator_range<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > >, ranges::v3::iterator_range<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >,
__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > > >, (lambda at ../include/range/v3/view/mask.hpp:188:32)>' here but deduced as 'ranges::v3::transform_view<ranges::v3::zip_view<ranges::v3::iterator_range<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > > >,
(lambda at ../include/range/v3/view/mask.hpp:188:32)>' in earlier return statement
return or_ranges(msks[0], msks[1]);
^
Насколько я понимаю, это говорит мне, что мой or_ranges
возвращает другой тип в зависимости от количества аргументов. (The zip
Я использую сохраняет знания о том, что было упаковано вместе).
Так что мне интересно, как мне набрать стирать то, что находится в диапазоне?
1 ответ
Вернуть ranges::v3::any_input_view < bool >
вместо auto
,
Это будет в 10 раз медленнее даже в оптимизированных сборках. Тип стирания стоит дорого.
Раскрученное вручную решение, которое знает, что входной диапазон имеет длину, и получает данные в буферизованных блоках, прежде чем распродать их, может, вероятно, приблизить производительность к не стираемым типам. Я ожидаю, что это все равно будет заметно медленнее.