patterncppMinor
Views and ranges for tuple-like objects
Viewed 0 times
objectslikeviewsrangestupleforand
Problem
This interesting idea came up when I was designing the
But unfortunately, this way we can only iterate over the entire tuple-like object, unlike
I guess theoretically it is possible to create some kind of heterogeneous iterator, but that feels kind of weird, because iterator types usually inherit from
So I think for tuple-like objects, a good way is to create some kind of ranges or views into the original objects, specified by indices. A range is a tuple of appropriate types of references to consecutive elements in the original tuple and preserves element order. A view is a tuple of appropriate types of references to possibly non-consecutive elements in the original tuple and does not necessarily preserve element order. Examples (pseudo-code):
Then, we will be able to do something like:
Enough examples. Time for implementation (C++14):
```
#include
#include
namespace detail {
template
constexpr auto make_tuple_range_impl(std::index_sequence,
Tuple&& t) noexcept
{
return std::forward_as_tuple(
std::get(
for_each for tuple-like objects in this post. The for_each in that post makes it possible to write code like:auto t = std::make_tuple(42, 'c', 3.14);
for_each(t, [](auto x) { std::cout << x << '\n'; });But unfortunately, this way we can only iterate over the entire tuple-like object, unlike
std::for_each, which, by accepting iterators, enables us to iterate over only a part of a collection. If only we could achieve something similar for tuple-likes!I guess theoretically it is possible to create some kind of heterogeneous iterator, but that feels kind of weird, because iterator types usually inherit from
std::iterator for some fixed T.So I think for tuple-like objects, a good way is to create some kind of ranges or views into the original objects, specified by indices. A range is a tuple of appropriate types of references to consecutive elements in the original tuple and preserves element order. A view is a tuple of appropriate types of references to possibly non-consecutive elements in the original tuple and does not necessarily preserve element order. Examples (pseudo-code):
(lvalue) std::tuple:
range : std::tuple<>
range : std::tuple
range : std::tuple
view : std::tuple
view: std::tuple
(rvalue) std::tuple:
range: std::tuple
view : std::tuple
(lvalue) std::tuple:
range: std::tuple
...Then, we will be able to do something like:
auto t = std::make_tuple(42, 'c', 3.14);
for_each(make_tuple_range(t), [](auto x) { std::cout (t), [](auto x) { std::cout (t), [](auto& x) { x += 1; });
for_each(t, [](auto x) { std::cout << x << ' '; });
// prints: 42 d 4.14Enough examples. Time for implementation (C++14):
```
#include
#include
namespace detail {
template
constexpr auto make_tuple_range_impl(std::index_sequence,
Tuple&& t) noexcept
{
return std::forward_as_tuple(
std::get(
Solution
My 2 cents:
I think you should restructure your code so that a range is simply a contiguous
(there may need to be forwarding in there, I'm not sure.)
I think you should restructure your code so that a range is simply a contiguous
index_sequence; and taking a subtuple by range is simply taking those elements corresponding to the index sequence. So you would implement a make_index_range which is similar to std::make_index_sequence, and then using that range you would have something liketemplate
constexpr auto subtuple(F f, Tuple t, std::index_sequence) {
return std::make_tuple(std::get>(t)...);
}(there may need to be forwarding in there, I'm not sure.)
Code Snippets
template <class F, Tuple t, size_t... Is>
constexpr auto subtuple(F f, Tuple t, std::index_sequence<Is...>) {
return std::make_tuple(std::get<std::integral_constant<size_t, Is>>(t)...);
}Context
StackExchange Code Review Q#134856, answer score: 2
Revisions (0)
No revisions yet.