patterncppMinor
Chain multiple containers
Viewed 0 times
containersmultiplechain
Problem
Python has
Currently, the objects that
First, some metaprogramming boilerplate:
(
And now the main event:
```
template
class Chainer {
using sequence = std::make_index_sequence;
using deref_type = nondecay_common_type_t...>;
public:
Chainer(Containers&&... c)
: containers(std::forward(c)...)
{ }
class iterator
{
public:
iterator(iter_pair_t... pairs)
: iter_pairs(pairs...)
{ }
deref_ty
itertools.chain(), but C++ has nothing. This is my attempt to implement such a thing. Looking mainly for comments about potentially smarter ways of doing things or potential pitfalls this code falls into based on its current implementation.Currently, the objects that
chain() will give back will be a reference if all the corresponding containers dereference to the same type, otherwise it will be a value (e.g. chaining a vector and deque will give an int&, but if the second was a deque instead would give an int).First, some metaprogramming boilerplate:
namespace adl_details {
using std::begin;
using std::end;
template
auto adl_begin(C&& c) {
return begin(std::forward(c));
}
template
auto adl_end(C&& c) {
return end(std::forward(c));
}
}
using adl_details::adl_begin;
using adl_details::adl_end;
template
using iter_t = decltype(adl_begin(std::declval()));
template
using iter_pair_t = std::pair, iter_t>;
template
using deref_t = decltype(*std::declval>());
template
struct type_is { using type = T; };
template
struct nondecay_common_type;
template
using nondecay_common_type_t = typename nondecay_common_type::type;
template
struct nondecay_common_type : type_is { };
template
T makeT();
template
struct nondecay_common_type
: type_is() : std::declval>())>
{ };(
nondecay_common_type is necessary because std::common_type_t yields int but I want it to yield int&. makeT is necessary because if I use std::declval, std::common_type_t would yield int&& but I want it to yield int). And now the main event:
```
template
class Chainer {
using sequence = std::make_index_sequence;
using deref_type = nondecay_common_type_t...>;
public:
Chainer(Containers&&... c)
: containers(std::forward(c)...)
{ }
class iterator
{
public:
iterator(iter_pair_t... pairs)
: iter_pairs(pairs...)
{ }
deref_ty
Solution
Try using ranges instead of iterators. E.g. using Eric Niebler's range-v3 library, you can write
Live Example. Using Boost.Range, a similar result can be obtained, but it's not as clean as using range-v3.
#include
#include
#include
int main()
{
using namespace ranges;
std::vector his_face{"this", "is", "his", "face"};
std::vector another_mess{"another", "fine", "mess"};
std::cout << view::concat(his_face, another_mess);
}Live Example. Using Boost.Range, a similar result can be obtained, but it's not as clean as using range-v3.
Code Snippets
#include <iostream>
#include <vector>
#include <range/v3/view/concat.hpp>
int main()
{
using namespace ranges;
std::vector<std::string> his_face{"this", "is", "his", "face"};
std::vector<std::string> another_mess{"another", "fine", "mess"};
std::cout << view::concat(his_face, another_mess);
}Context
StackExchange Code Review Q#105117, answer score: 3
Revisions (0)
No revisions yet.