merging multiple arrays using boost::join - c++

Is it a better idea to use boost::join to access and change the values of different arrays?
I have defined a member array inside class element.
class element
{
public:
element();
int* get_arr();
private:
int m_arr[4];
}
At different place, I'm accessing these arrays and joined together using boost::join and changing the array values.
//std::vector<element> elem;
auto temp1 = boost::join(elem[0].get_arr(),elem[1].get_arr());
auto joined_arr = boost::join(temp1,elem[2].get_arr());
//now going to change the values of the sub array
for(auto& it:joined_arr)
{
it+= sample[i];
i++;
}
Is this a good idea to modify the values of array in the class as above?

In your code you probably want to join the 4-elements arrays. To do that change the signature of get_arr to:
typedef int array[4];
array& get_arr() { return m_arr; }
So that the array size does not get lost.
Performance-wise there is a non-zero cost for accessing elements through the joined view. A double for loop is going to be most efficient, and easily readable too, e.g.:
for(auto& e : elem)
for(auto& a : e.get_arr())
a += sample[i++];

boost::join returns a more complicated type every composition step. At some point you might exceed the compiler's limits on inlining so that you're going to have a runtime cost¹.
Thinking outside the box, it really looks like you are creating a buffer abstraction that allows you to do scatter/gather like IO with few allocations.
As it happens, Boost Asio has nice abstractions for this², and you could use that: http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/MutableBufferSequence.html
As I found out in an earlier iteration of this answer code that abstraction sadly only works for buffers accessed through native char-type elements. That was no good.
So, in this rewrite I present a similar abstraction, which consists of nothing than an "hierarchical iterator" that knows how to iterate a sequence of "buffers" (in this implementation, any range will do).
You can choose to operate on a sequence of ranges directly, e.g.:
std::vector<element> seq(3); // tie 3 elements together as buffer sequence
element& b = seq[1];
Or, without any further change, by reference:
element a, b, c;
std::vector<std::reference_wrapper<element> > seq {a,b,c}; // tie 3 elements together as buffer sequence
The C++ version presented at the bottom demonstrates this approach Live On Coliru
The Iterator Implementation
I've used Boost Range and Boost Iterator:
template <typename Seq,
typename WR = typename Seq::value_type,
typename R = typename detail::unwrap<WR>::type,
typename V = typename boost::range_value<R>::type
>
struct sequence_iterator : boost::iterator_facade<sequence_iterator<Seq,WR,R,V>, V, boost::forward_traversal_tag> {
using OuterIt = typename boost::range_iterator<Seq>::type;
using InnerIt = typename boost::range_iterator<R>::type;
// state
Seq& _seq;
OuterIt _ocur, _oend;
InnerIt _icur, _iend;
static sequence_iterator begin(Seq& seq) { return {seq, boost::begin(seq), boost::end(seq)}; }
static sequence_iterator end(Seq& seq) { return {seq, boost::end(seq), boost::end(seq)}; }
// the 3 facade operations
bool equal(sequence_iterator const& rhs) const {
return ((_ocur==_oend) && (rhs._ocur==rhs._oend))
|| (std::addressof(_seq) == std::addressof(rhs._seq) &&
_ocur == rhs._ocur && _oend == rhs._oend &&
_icur == rhs._icur && _iend == rhs._iend);
}
void increment() {
if (++_icur == _iend) {
++_ocur;
setup();
}
}
V& dereference() const {
assert(_ocur != _oend);
assert(_icur != _iend);
return *_icur;
}
private:
void setup() { // to be called after entering a new sub-range in the sequence
while (_ocur != _oend) {
_icur = boost::begin(detail::get(*_ocur));
_iend = boost::end(detail::get(*_ocur));
if (_icur != _iend)
break;
++_ocur; // skid over, this enables simple increment() logic
}
}
sequence_iterator(Seq& seq, OuterIt cur, OuterIt end)
: _seq(seq), _ocur(cur), _oend(end) { setup(); }
};
That's basically the same kind of iterator as boost::asio::buffers_iterator but it doesn't assume an element type. Now, creating sequence_iterators for any sequence of ranges is as simple as:
template <typename Seq> auto buffers_begin(Seq& seq) { return sequence_iterator<Seq>::begin(seq); }
template <typename Seq> auto buffers_end(Seq& seq) { return sequence_iterator<Seq>::end(seq); }
Implementing Your Test Program
Live On Coliru
// DEMO
struct element {
int peek_first() const { return m_arr[0]; }
auto begin() const { return std::begin(m_arr); }
auto end() const { return std::end(m_arr); }
auto begin() { return std::begin(m_arr); }
auto end() { return std::end(m_arr); }
private:
int m_arr[4] { };
};
namespace boost { // range adapt
template <> struct range_iterator<element> { using type = int*; };
// not used, but for completeness:
template <> struct range_iterator<element const> { using type = int const*; };
template <> struct range_const_iterator<element> : range_iterator<element const> {};
}
#include <algorithm>
#include <iostream>
#include <vector>
template <typename Output, typename Input, typename Operation>
size_t process(Output& output, Input const& input, Operation op) {
auto ib = boost::begin(input), ie = boost::end(input);
auto ob = boost::begin(output), oe = boost::end(output);
size_t n = 0;
for (;ib!=ie && ob!=oe; ++n) {
op(*ob++, *ib++);
}
return n;
}
int main() {
element a, b, c;
std::vector<std::reference_wrapper<element> > seq {a,b,c}; // tie 3 elements together as buffer sequence
//// Also supported, container of range objects directly:
// std::list<element> seq(3); // tie 3 elements together as buffer sequence
// element& b = seq[1];
std::vector<int> const samples {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32
};
using boost::make_iterator_range;
auto input = make_iterator_range(samples);
auto output = make_iterator_range(buffers_begin(seq), buffers_end(seq));
while (auto n = process(output, input, [](int& el, int sample) { el += sample; })) {
std::cout << "Copied " << n << " samples, b starts with " << b.peek_first() << "\n";
input.advance_begin(n);
}
}
Prints
Copied 12 samples, b starts with 5
Copied 12 samples, b starts with 22
Copied 8 samples, b starts with 51
Full Listing, C++11 Compatible
Live On Coliru
#include <boost/iterator/iterator_facade.hpp>
#include <boost/range/iterator_range.hpp>
#include <functional> // std::reference_wrapper
namespace detail {
template<typename T> constexpr T& get(T &t) { return t; }
template<typename T> constexpr T const& get(T const &t) { return t; }
template<typename T> constexpr T& get(std::reference_wrapper<T> rt) { return rt; }
template <typename T> struct unwrap { using type = T; };
template <typename T> struct unwrap<std::reference_wrapper<T> > { using type = T; };
}
template <typename Seq,
typename WR = typename Seq::value_type,
typename R = typename detail::unwrap<WR>::type,
typename V = typename boost::range_value<R>::type
>
struct sequence_iterator : boost::iterator_facade<sequence_iterator<Seq,WR,R,V>, V, boost::forward_traversal_tag> {
using OuterIt = typename boost::range_iterator<Seq>::type;
using InnerIt = typename boost::range_iterator<R>::type;
// state
Seq& _seq;
OuterIt _ocur, _oend;
InnerIt _icur, _iend;
static sequence_iterator begin(Seq& seq) { return {seq, boost::begin(seq), boost::end(seq)}; }
static sequence_iterator end(Seq& seq) { return {seq, boost::end(seq), boost::end(seq)}; }
// the 3 facade operations
bool equal(sequence_iterator const& rhs) const {
return ((_ocur==_oend) && (rhs._ocur==rhs._oend))
|| (std::addressof(_seq) == std::addressof(rhs._seq) &&
_ocur == rhs._ocur && _oend == rhs._oend &&
_icur == rhs._icur && _iend == rhs._iend);
}
void increment() {
if (++_icur == _iend) {
++_ocur;
setup();
}
}
V& dereference() const {
assert(_ocur != _oend);
assert(_icur != _iend);
return *_icur;
}
private:
void setup() { // to be called after entering a new sub-range in the sequence
while (_ocur != _oend) {
_icur = boost::begin(detail::get(*_ocur));
_iend = boost::end(detail::get(*_ocur));
if (_icur != _iend)
break;
++_ocur; // skid over, this enables simple increment() logic
}
}
sequence_iterator(Seq& seq, OuterIt cur, OuterIt end)
: _seq(seq), _ocur(cur), _oend(end) { setup(); }
};
template <typename Seq> auto buffers_begin(Seq& seq) { return sequence_iterator<Seq>::begin(seq); }
template <typename Seq> auto buffers_end(Seq& seq) { return sequence_iterator<Seq>::end(seq); }
// DEMO
struct element {
int peek_first() const { return m_arr[0]; }
auto begin() const { return std::begin(m_arr); }
auto end() const { return std::end(m_arr); }
auto begin() { return std::begin(m_arr); }
auto end() { return std::end(m_arr); }
private:
int m_arr[4] { };
};
namespace boost { // range adapt
template <> struct range_iterator<element> { using type = int*; };
// not used, but for completeness:
template <> struct range_iterator<element const> { using type = int const*; };
template <> struct range_const_iterator<element> : range_iterator<element const> {};
}
#include <algorithm>
#include <iostream>
#include <vector>
template <typename Output, typename Input, typename Operation>
size_t process(Output& output, Input const& input, Operation op) {
auto ib = boost::begin(input), ie = boost::end(input);
auto ob = boost::begin(output), oe = boost::end(output);
size_t n = 0;
for (;ib!=ie && ob!=oe; ++n) {
op(*ob++, *ib++);
}
return n;
}
int main() {
element a, b, c;
std::vector<std::reference_wrapper<element> > seq {a,b,c}; // tie 3 elements together as buffer sequence
//// Also supported, container of range objects directly:
// std::list<element> seq(3); // tie 3 elements together as buffer sequence
// element& b = seq[1];
std::vector<int> const samples {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32
};
using boost::make_iterator_range;
auto input = make_iterator_range(samples);
auto output = make_iterator_range(buffers_begin(seq), buffers_end(seq));
while (auto n = process(output, input, [](int& el, int sample) { el += sample; })) {
std::cout << "Copied " << n << " samples, b starts with " << b.peek_first() << "\n";
input.advance_begin(n);
}
}
¹ I'm ignoring the compile-time cost and the lurking dangers with the pattern of auto x = complicated_range_composition when that complicated range composition contains references to temporaries: this is a frequent source of UB bugs
² which have been adopted by various other libraries, like Boost Beast, Boost Process and seem to have found their way into the Networking TS for C++20: Header <experimental/buffer> synopsis (PDF)

Related

Is there a way to iterate a vector in reverse using for each loop? [duplicate]

Is there a container adapter that would reverse the direction of iterators so I can iterate over a container in reverse with range-based for-loop?
With explicit iterators I would convert this:
for (auto i = c.begin(); i != c.end(); ++i) { ...
into this:
for (auto i = c.rbegin(); i != c.rend(); ++i) { ...
I want to convert this:
for (auto& i: c) { ...
to this:
for (auto& i: std::magic_reverse_adapter(c)) { ...
Is there such a thing or do I have to write it myself?
Actually Boost does have such adaptor: boost::adaptors::reverse.
#include <list>
#include <iostream>
#include <boost/range/adaptor/reversed.hpp>
int main()
{
std::list<int> x { 2, 3, 5, 7, 11, 13, 17, 19 };
for (auto i : boost::adaptors::reverse(x))
std::cout << i << '\n';
for (auto i : x)
std::cout << i << '\n';
}
Actually, in C++14 it can be done with a very few lines of code.
This is a very similar in idea to #Paul's solution. Due to things missing from C++11, that solution is a bit unnecessarily bloated (plus defining in std smells). Thanks to C++14 we can make it a lot more readable.
The key observation is that range-based for-loops work by relying on begin() and end() in order to acquire the range's iterators. Thanks to ADL, one doesn't even need to define their custom begin() and end() in the std:: namespace.
Here is a very simple-sample solution:
// -------------------------------------------------------------------
// --- Reversed iterable
template <typename T>
struct reversion_wrapper { T& iterable; };
template <typename T>
auto begin (reversion_wrapper<T> w) { return std::rbegin(w.iterable); }
template <typename T>
auto end (reversion_wrapper<T> w) { return std::rend(w.iterable); }
template <typename T>
reversion_wrapper<T> reverse (T&& iterable) { return { iterable }; }
This works like a charm, for instance:
template <typename T>
void print_iterable (std::ostream& out, const T& iterable)
{
for (auto&& element: iterable)
out << element << ',';
out << '\n';
}
int main (int, char**)
{
using namespace std;
// on prvalues
print_iterable(cout, reverse(initializer_list<int> { 1, 2, 3, 4, }));
// on const lvalue references
const list<int> ints_list { 1, 2, 3, 4, };
for (auto&& el: reverse(ints_list))
cout << el << ',';
cout << '\n';
// on mutable lvalue references
vector<int> ints_vec { 0, 0, 0, 0, };
size_t i = 0;
for (int& el: reverse(ints_vec))
el += i++;
print_iterable(cout, ints_vec);
print_iterable(cout, reverse(ints_vec));
return 0;
}
prints as expected
4,3,2,1,
4,3,2,1,
3,2,1,0,
0,1,2,3,
NOTE std::rbegin(), std::rend(), and std::make_reverse_iterator() are not yet implemented in GCC-4.9. I write these examples according to the standard, but they would not compile in stable g++. Nevertheless, adding temporary stubs for these three functions is very easy. Here is a sample implementation, definitely not complete but works well enough for most cases:
// --------------------------------------------------
template <typename I>
reverse_iterator<I> make_reverse_iterator (I i)
{
return std::reverse_iterator<I> { i };
}
// --------------------------------------------------
template <typename T>
auto rbegin (T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
// const container variants
template <typename T>
auto rbegin (const T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (const T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
Got this example from cppreference. It works with:
GCC 10.1+ with flag -std=c++20
#include <ranges>
#include <iostream>
int main()
{
static constexpr auto il = {3, 1, 4, 1, 5, 9};
std::ranges::reverse_view rv {il};
for (int i : rv)
std::cout << i << ' ';
std::cout << '\n';
for(int i : il | std::views::reverse)
std::cout << i << ' ';
}
If you can use range v3 , you can use the reverse range adapter ranges::view::reverse which allows you to view the container in reverse.
A minimal working example:
#include <iostream>
#include <vector>
#include <range/v3/view.hpp>
int main()
{
std::vector<int> intVec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (auto const& e : ranges::view::reverse(intVec)) {
std::cout << e << " ";
}
std::cout << std::endl;
for (auto const& e : intVec) {
std::cout << e << " ";
}
std::cout << std::endl;
}
See DEMO 1.
Note: As per Eric Niebler, this feature will be available in C++20. This can be used with the <experimental/ranges/range> header. Then the for statement will look like this:
for (auto const& e : view::reverse(intVec)) {
std::cout << e << " ";
}
See DEMO 2
This should work in C++11 without boost:
namespace std {
template<class T>
T begin(std::pair<T, T> p)
{
return p.first;
}
template<class T>
T end(std::pair<T, T> p)
{
return p.second;
}
}
template<class Iterator>
std::reverse_iterator<Iterator> make_reverse_iterator(Iterator it)
{
return std::reverse_iterator<Iterator>(it);
}
template<class Range>
std::pair<std::reverse_iterator<decltype(begin(std::declval<Range>()))>, std::reverse_iterator<decltype(begin(std::declval<Range>()))>> make_reverse_range(Range&& r)
{
return std::make_pair(make_reverse_iterator(begin(r)), make_reverse_iterator(end(r)));
}
for(auto x: make_reverse_range(r))
{
...
}
Does this work for you:
#include <iostream>
#include <list>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator_range.hpp>
int main(int argc, char* argv[]){
typedef std::list<int> Nums;
typedef Nums::iterator NumIt;
typedef boost::range_reverse_iterator<Nums>::type RevNumIt;
typedef boost::iterator_range<NumIt> irange_1;
typedef boost::iterator_range<RevNumIt> irange_2;
Nums n = {1, 2, 3, 4, 5, 6, 7, 8};
irange_1 r1 = boost::make_iterator_range( boost::begin(n), boost::end(n) );
irange_2 r2 = boost::make_iterator_range( boost::end(n), boost::begin(n) );
// prints: 1 2 3 4 5 6 7 8
for(auto e : r1)
std::cout << e << ' ';
std::cout << std::endl;
// prints: 8 7 6 5 4 3 2 1
for(auto e : r2)
std::cout << e << ' ';
std::cout << std::endl;
return 0;
}
Sorry but with current C++ (apart from C++20) all these solutions do seem to be inferior to just use index-based for. Nothing here is just "a few lines of code". So, yes: iterate via a simple int-loop. That's the best solution.
template <typename C>
struct reverse_wrapper {
C & c_;
reverse_wrapper(C & c) : c_(c) {}
typename C::reverse_iterator begin() {return c_.rbegin();}
typename C::reverse_iterator end() {return c_.rend(); }
};
template <typename C, size_t N>
struct reverse_wrapper< C[N] >{
C (&c_)[N];
reverse_wrapper( C(&c)[N] ) : c_(c) {}
typename std::reverse_iterator<const C *> begin() { return std::rbegin(c_); }
typename std::reverse_iterator<const C *> end() { return std::rend(c_); }
};
template <typename C>
reverse_wrapper<C> r_wrap(C & c) {
return reverse_wrapper<C>(c);
}
eg:
int main(int argc, const char * argv[]) {
std::vector<int> arr{1, 2, 3, 4, 5};
int arr1[] = {1, 2, 3, 4, 5};
for (auto i : r_wrap(arr)) {
printf("%d ", i);
}
printf("\n");
for (auto i : r_wrap(arr1)) {
printf("%d ", i);
}
printf("\n");
return 0;
}
You could simply use BOOST_REVERSE_FOREACH which iterates backwards. For example, the code
#include <iostream>
#include <boost\foreach.hpp>
int main()
{
int integers[] = { 0, 1, 2, 3, 4 };
BOOST_REVERSE_FOREACH(auto i, integers)
{
std::cout << i << std::endl;
}
return 0;
}
generates the following output:
4
3
2
1
0
If not using C++14, then I find below the simplest solution.
#define METHOD(NAME, ...) auto NAME __VA_ARGS__ -> decltype(m_T.r##NAME) { return m_T.r##NAME; }
template<typename T>
struct Reverse
{
T& m_T;
METHOD(begin());
METHOD(end());
METHOD(begin(), const);
METHOD(end(), const);
};
#undef METHOD
template<typename T>
Reverse<T> MakeReverse (T& t) { return Reverse<T>{t}; }
Demo.
It doesn't work for the containers/data-types (like array), which doesn't have begin/rbegin, end/rend functions.

What is the most efficient way to add arbitrary number of elements to an std::vector in C++?

I have a defined class A and an std::vector vec that stores a series of A instances. I attempt to write a function that appends an arbitrary number of A instances to vec.
Should I use vec.reserve() along with vec.push_back() since constantly resizing vector is expensive? Or, should I use vec.insert()?
Currently, I'm not sure if I should design the function to accept a variable number of arguments using variadic functions or a vector of A instances that I'd like to combine and then concatenate with vec?
What is an efficient way to design this function (speed is critical and A is a complex class)?
The following should cover common cases, I think. The rref_capture trick is from this answer. The point of it all is that the values are moved whenever possible.
You can also use a variadic template version, as given in the other answer.
// https://github.com/KubaO/stackoverflown/tree/master/questions/vector-append-40274282
#include <array>
#include <cassert>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <vector>
template<typename T>
class rref_capture {
T* ptr;
public:
rref_capture(T&& x) : ptr(&x) {}
operator T&& () const { return std::move(*ptr); } // restitute rvalue ref
};
template <typename T>
void append(std::vector<T> & v,
typename std::decay<std::initializer_list<rref_capture<T>>>::type u) {
v.reserve(v.size() + u.size());
for (auto && item : u)
v.push_back(std::move(item));
}
template <typename T, typename U>
void append(std::vector<T> & v, U && u) {
v.reserve(v.size() + std::distance(std::begin(u), std::end(u)));
for (auto & item : u)
v.push_back(std::move(item));
}
template <typename T, typename U>
void append(std::vector<T> & v, U & u) {
v.reserve(v.size() + std::distance(std::begin(u), std::end(u)));
for (auto & item : u)
v.push_back(item);
}
struct A {
static int copies, moves;
A() {}
A(A&&) { moves++; }
A(const A&) { copies++; }
A& operator=(const A&) { copies++; return *this; }
static void reset() { A::copies = 0; A::moves = 0; }
};
int A::copies, A::moves;
int main() {
std::vector<A> vec;
vec.reserve(100);
A::reset();
append(vec, {A(), A()});
assert(A::copies == 0 && A::moves == 2 && vec.size() == 2);
auto vec2 = vec;
A::reset();
append(vec, vec2);
assert(A::copies == 2 && A::moves == 0 && vec.size() == 4);
A::reset();
append(vec, std::move(vec2));
assert(A::copies == 0 && A::moves == 2 && vec.size() == 6);
A::reset();
append(vec, std::array<A,2>{A(), A()});
assert(A::copies == 0 && A::moves == 2 && vec.size() == 8);
const std::vector<A> cvec{2};
A::reset();
append(vec, cvec);
assert(A::copies == 2 && A::moves == 0 && vec.size() == 10);
A arr[2];
A::reset();
append(vec, arr);
assert(A::copies == 2 && A::moves == 0 && vec.size() == 12);
}
Well... I suppose you could use reserve() one time and then add the single element using push_back().
The following example use int instead of class A but should give the idea
#include <vector>
#include <iostream>
template <typename T>
void appendT (std::vector<T> & v)
{ }
template <typename T, typename ... Ts>
void appendT (std::vector<T> & v, T t, Ts ... ts)
{
v.push_back(t);
appendT(v, ts...);
}
template <typename T, typename ... Ts>
void appendTs (std::vector<T> & v, Ts ... ts)
{
v.reserve(v.size() + sizeof...(Ts));
appendT(v, ts...);
}
int main()
{
std::vector<int> v { 2, 3, 5 };
appendTs(v, 7, 11, 13, 17);
for ( auto const & i : v )
std::cout << ' ' << i; // print " 2 3 5 7 11 13 17"
std::cout << std::endl;
}
If you don't like the recursive solution, you can write an appendTs() that do all the works (but I don't know how to avoid the annoing "warning: unused variable 'unused'" I know how to avoid the warning but I don't know if it's a good idea Kuba Ober suggested me an elegant way to avoid the warning)
#include <vector>
#include <iostream>
template <typename T, typename ... Ts>
void appendTs (std::vector<T> & v, Ts ... ts)
{
v.reserve(v.size() + sizeof...(Ts));
// the first '0' is to avoid an error when sizeof...(Ts) is zero
char unused[] { '0', (v.push_back(ts), '0')... };
// the following statement is to avoid an annoing "unused variable
// 'unused'" warning (thanks Kuba Ober)
(void)unused;
}
int main()
{
std::vector<int> v { 2, 3, 5 };
appendTs(v, 7, 11, 13, 17);
for ( auto const & i : v )
std::cout << ' ' << i; // print " 2 3 5 7 11 13 17"
std::cout << std::endl;
}

C++11 for each loop with more than one variable

I would like to translate the following traditional for loop into a C++11 for-each loop without extra looping constructs:
int a[] = { 5, 6, 7, 8, 9, 10 };
int b[] = { 50, 60, 70, 80, 90, 100 };
// Swap a and b array elements
for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{
a[i] ^= b[i]; b[i] ^= a[i]; a[i] ^= b[i];
}
Does there exist any way by which it is possible to provide more than one variable in the C++11 for-each loop like:
for (int i, int j : ...)
There is no built-in way to do this. If you can use Boost, boost::combine will work for iterating two (or more) ranges simultaneously (Does boost offer make_zip_range?, How can I iterate over two vectors simultaneously using BOOST_FOREACH?):
for (boost::tuple<int&, int&> ij : boost::combine(a, b)) {
int& i = boost::get<0>(ij);
int& j = boost::get<1>(ij);
// ...
}
Unfortunately accessing the elements within the tuple elements of the zipped range is highly verbose. C++17 will make this much more readable using structured binding:
for (auto [&i, &j] : boost::combine(a, b)) {
// ...
}
Since you don't need to break out of the loop or return from the enclosing function, you could use boost::range::for_each with the body of your loop as a lambda:
boost::range::for_each(a, b, [](int& i, int& j)
{
// ...
});
zip or combine ranges are common in many range libraries.
Writing one strong enough for a for(:) loop isn't hard however.
First we write a basic range type:
template<class It>
struct range_t {
It b,e;
It begin() const{ return b; }
It end() const{ return e; }
range_t without_front( std::size_t count = 1 ) const {
return {std::next(begin()), end()};
}
bool empty() const { return begin()==end(); }
};
template<class It>
range_t<It> range( It b, It e ) { return {b,e}; }
template<class C>
auto range( C& c ) {
using std::begin; using std::end;
return range( begin(c), end(c) );
};
Then we write an iterator that works with ranges (easier than with iterators):
template<class R1, class R2>
struct double_foreach_iterator {
R1 r1;
R2 r2;
void operator++() { r1 = r1.without_front(); r2 = r2.without_front(); }
bool is_end() const { return r1.empty() || r2.empty(); }
auto operator*()const {
return std::tie( *r1.begin(), *r2.begin() );
}
using self=double_foreach_iterator;
auto cur() const {
return std::make_tuple( r1.begin(), r2.begin() );
}
friend bool operator==( self const& lhs, self const& rhs ) {
if (lhs.is_end() || rhs.is_end())
return lhs.is_end() == rhs.is_end();
return lhs.cur() == rhs.cur();
}
friend bool operator!=( self const& lhs, self const& rhs ) {
return !(lhs==rhs);
}
};
now we double iterate:
template<class A, class B>
auto zip_iterate(
A& a, B& b
) {
auto r1 = range(a);
auto r2 = range(b);
auto r1end = range(r1.end(), r1.end());
auto r2end = range(r2.end(), r2.end());
using it = double_foreach_iterator<decltype(r1), decltype(r2)>;
return range( it{r1, r2}, it{r1end, r2end} );
}
which gives us:
for (auto tup : zip_iterate(a, b)) {
int& i = std::get<0>(tup);
int& j = std::get<1>(tup);
// ...
}
or in C++17:
for (auto&& [i, j] : zip_iterate(a, b)) {
// ...
}
My zip iterate does not assume the two containers are of the same length, and will iterate to the length of the shorter one.
live example.
Just for fun.
The following isn't intended to be a serious answer to the question but just an exercise to try to understand the potentiality of C++11 (so, please, be patient).
The following is an example of a class (a draft of a class) that receive a couple of container (with size() method), with the same size (exception otherwise), and of a custom iterator that return a std::pair of std::reference_wrapper to n-position elements.
With a simple use example that show that it's possible to change the value in the starting containers.
Doesn't work with old C-style arrays but works with std::array. We're talking about C++11 so I suppose we could impose the use of std::array.
#include <array>
#include <vector>
#include <iostream>
#include <functional>
template <typename T1, typename T2>
class pairWrapper
{
public:
using V1 = typename std::remove_reference<decltype((T1().at(0)))>::type;
using V2 = typename std::remove_reference<decltype((T2().at(0)))>::type;
using RW1 = std::reference_wrapper<V1>;
using RW2 = std::reference_wrapper<V2>;
class it
{
public:
it (pairWrapper & pw0, std::size_t p0): pos{p0}, pw{pw0}
{ }
it & operator++ ()
{ ++pos; return *this; }
bool operator!= (const it & it0)
{ return pos != it0.pos; }
std::pair<RW1, RW2> & operator* ()
{
static std::pair<RW1, RW2>
p{std::ref(pw.t1[0]), std::ref(pw.t2[0])};
p.first = std::ref(pw.t1[pos]);
p.second = std::ref(pw.t2[pos]);
return p;
}
private:
std::size_t pos;
pairWrapper & pw;
};
it begin()
{ return it(*this, 0U); }
it end()
{ return it(*this, len); }
pairWrapper (T1 & t10, T2 & t20) : len{t10.size()}, t1{t10}, t2{t20}
{ if ( t20.size() != len ) throw std::logic_error("no same len"); }
private:
const std::size_t len;
T1 & t1;
T2 & t2;
};
template <typename T1, typename T2>
pairWrapper<T1, T2> makePairWrapper (T1 & t1, T2 & t2)
{ return pairWrapper<T1, T2>(t1, t2); }
int main()
{
std::vector<int> v1 { 1, 2, 3, 4 };
std::array<long, 4> v2 { { 11L, 22L, 33L, 44L } };
for ( auto & p : makePairWrapper(v1, v2) )
{
std::cout << '{' << p.first << ", " << p.second << '}' << std::endl;
p.first += 3;
p.second += 55;
}
for ( const auto & i : v1 )
std::cout << '[' << i << ']' << std::endl;
for ( const auto & l : v2 )
std::cout << '[' << l << ']' << std::endl;
return 0;
}
p.s.: sorry for my bad English

is there a way to pass nested initializer lists in C++11 to construct a 2D matrix?

Imagine you have a simple matrix class
template <typename T = double>
class Matrix {
T* data;
size_t row, col;
public:
Matrix(size_t m, size_t n) : row(m), col(n), data(new T[m*n]) {}
//...
friend std::ostream& operator<<(std::ostream& os, const Matrix& m) {
for (int i=0; i<m.row; ++i) {
for (int j=0; j<m.col; ++j)
os<<" "<<m.data[i + j*m.row];
os<<endl;
}
return os;
}
};
Is there a way that I can initialize this matrix with an initializer list? I mean to obtain the sizes of the matrix and the elements from an initializer list. Something like the following code:
Matrix m = { {1., 3., 4.}, {2., 6, 2.}};
would print
1 3 4
2 6 2
Looking forward to your answers. Thank you all.
aa
EDIT
So I worked on your suggestions to craft a somewhat generic array that initializes elements using initializer lists. But this is the most generic I could obtain.
I would appreciate if any of you have any suggestions as to make it a more generic class.
Also, a couple of questions:
Is it fine that a derived class initializes the state of the base class? I'm not calling the base constructor because of this, but should I call it anyways?
I defined the destructor a the Generic_base class as protected, is this the right way to do it?
Is there any foreseeable way to carry out the code that belongs to the constructor of the initializer in a more generic way? I mean to have one general constructor that takes care of all cases?
I included just the necessary code to illustrate the use of initializer lists in construction. When going to higher dimensions it gets messy, but I did one just to check the code.
#include <iostream>
#include <cassert>
using std::cout;
using std::endl;
template <int d, typename T>
class Generic_base {
protected:
typedef T value_type;
Generic_base() : n_(), data_(nullptr){}
size_t n_[d] = {0};
value_type* data_;
};
template <int d, typename T>
class Generic_traits;
template <typename T>
class Generic_traits<1,T> : public Generic_base<1,T> {
protected:
typedef T value_type;
typedef Generic_base<1,T> base_type;
typedef std::initializer_list<T> initializer_type;
using base_type::n_;
using base_type::data_;
public:
Generic_traits(initializer_type l) {
assert(l.size() > 0);
n_[0] = l.size();
data_ = new T[n_[0]];
int i = 0;
for (const auto& v : l)
data_[i++] = v;
}
};
template <typename T>
class Generic_traits<2,T> : public Generic_base<2,T> {
protected:
typedef T value_type;
typedef Generic_base<2,T> base_type;
typedef std::initializer_list<T> list_type;
typedef std::initializer_list<list_type> initializer_type;
using base_type::n_;
using base_type::data_;
public:
Generic_traits(initializer_type l) {
assert(l.size() > 0);
n_[0] = l.size();
n_[1] = l.begin()->size();
data_ = new T[n_[0]*n_[1]];
int i = 0, j = 0;
for (const auto& r : l) {
assert(r.size() == n_[1]);
for (const auto& v : r) {
data_[i + j*n_[0]] = v;
++j;
}
j = 0;
++i;
}
}
};
template <typename T>
class Generic_traits<4,T> : public Generic_base<4,T> {
protected:
typedef T value_type;
typedef Generic_base<4,T> base_type;
typedef std::initializer_list<T> list_type;
typedef std::initializer_list<list_type> llist_type;
typedef std::initializer_list<llist_type> lllist_type;
typedef std::initializer_list<lllist_type> initializer_type;
using base_type::n_;
using base_type::data_;
public:
Generic_traits(initializer_type l) {
assert(l.size() > 0);
assert(l.begin()->size() > 0);
assert(l.begin()->begin()->size() > 0);
assert(l.begin()->begin()->begin()->size() > 0);
size_t m = n_[0] = l.size();
size_t n = n_[1] = l.begin()->size();
size_t o = n_[2] = l.begin()->begin()->size();
n_[3] = l.begin()->begin()->begin()->size();
data_ = new T[m*n*o*n_[3]];
int i=0, j=0, k=0, p=0;
for (const auto& u : l) {
assert(u.size() == n_[1]);
for (const auto& v : u) {
assert(v.size() == n_[2]);
for (const auto& x : v) {
assert(x.size() == n_[3]);
for (const auto& y : x) {
data_[i + m*j + m*n*k + m*n*o*p] = y;
++p;
}
p = 0;
++k;
}
k = 0;
++j;
}
j = 0;
++i;
}
}
};
template <int d, typename T>
class Generic : public Generic_traits<d,T> {
public:
typedef Generic_traits<d,T> traits_type;
typedef typename traits_type::base_type base_type;
using base_type::n_;
using base_type::data_;
typedef typename traits_type::initializer_type initializer_type;
// initializer list constructor
Generic(initializer_type l) : traits_type(l) {}
size_t size() const {
size_t n = 1;
for (size_t i=0; i<d; ++i)
n *= n_[i];
return n;
}
friend std::ostream& operator<<(std::ostream& os, const Generic& a) {
for (int i=0; i<a.size(); ++i)
os<<" "<<a.data_[i];
return os<<endl;
}
};
int main()
{
// constructors for initializer lists
Generic<1, double> y = { 1., 2., 3., 4.};
cout<<"y -> "<<y<<endl;
Generic<2, double> C = { {1., 2., 3.}, {4., 5., 6.} };
cout<<"C -> "<<C<<endl;
Generic<4, double> TT = { {{{1.}, {7.}, {13.}, {19}}, {{2}, {8}, {14}, {20}}, {{3}, {9}, {15}, {21}}}, {{{4.}, {10}, {16}, {22}}, {{5}, {11}, {17}, {23}}, {{6}, {12}, {18}, {24}}} };
cout<<"TT -> "<<TT<<endl;
return 0;
}
Which prints as expected:
y -> 1 2 3 4
C -> 1 4 2 5 3 6
TT -> 1 4 2 5 3 6 7 10 8 11 9 12 13 16 14 17 15 18 19 22 20 23 21 24
Why not?
Matrix(std::initializer_list<std::initializer_list<T>> lst) :
Matrix(lst.size(), lst.size() ? lst.begin()->size() : 0)
{
int i = 0, j = 0;
for (const auto& l : lst)
{
for (const auto& v : l)
{
data[i + j * row] = v;
++j;
}
j = 0;
++i;
}
}
And as stardust_ suggests - you should use vectors, not arrays here.
The main issue with using initializer lists to tackle this problem, is that their size is not easily accessible at compile time. It looks like this particular class is for dynamic matrices, but if you wanted to do this on the stack (usually for speed/locality reasons), here is a hint at what you need (C++17):
template<typename elem_t, std::size_t ... dim>
struct matrix
{
template<std::size_t ... n>
constexpr matrix(const elem_t (&...list)[n]) : data{}
{
auto pos = &data[0];
((pos = std::copy(list, list + n, pos)), ...);
}
elem_t data[(dim * ... * 1)];
};
template<typename ... elem_t, std::size_t ... n>
matrix(const elem_t (&...list)[n]) -> matrix<std::common_type_t<elem_t...>, sizeof...(n), (n * ... * 1) / sizeof...(n)>;
I had to tackle this same problem in my linear algebra library, so I understand how unintuitive this is at first. But if you instead pass a C-array into your constructor, you will have both type and size information of the values you've passed in. Also take note of the constuctor template argument deduction (CTAD) to abstract away the template arguments.
You can then create constexpr matrix objects like this (or, leave out constexpr to simply do this at runtime on the stack):
constexpr matrix mat{ {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
Which will initialize an object at compile time of type:
const matrix<int, 4, 3>
If C++20 is supported by your compiler, I would recommend adding a "requires" clause to the CTAD to ensure that all sub-arrays are the same size (mathematically-speaking, n1 == n2 == n3 == n4, etc).
Using std::vector::emplace_back() (longer)
Using std::vector, instead of plain old array, you can use std::vector::emplace_back() to fill the vector:
template <typename T = double>
class Matrix {
std::vector<T> data;
size_t row{}, col{}; // Non-static member initialization
public:
Matrix(size_t m, size_t n) : data(std::vector<T>(m * n)), row(m), col(n)
{ // ^ Keep the order in which the members are declared
}
Matrix(std::initializer_list<std::initializer_list<T>> lst)
: row(lst.size())
, col(lst.size() ? lst.begin()->size() : 0) // Minimal validation
{
// Eliminate reallocations as we already know the size of matrix
data.reserve(row * col);
for (auto const& r : lst) {
for (auto const &c : r) {
data.emplace_back(c);
}
}
}
};
int main() {
Matrix<double> d = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
}
Using std::vector::insert() (better and shorter)
As #Bob mentioned in a comment, you can use std::vector::insert() member function, instead of the inner emplace_back loop:
template <typename T = double>
class Matrix {
std::vector<T> data;
size_t row{}, col{}; // Non-static member initialization
public:
Matrix(size_t m, size_t n) : data(std::vector<T>(m * n)), row(m), col(n)
{ // ^ Keep the order in which the members are declared
}
Matrix(std::initializer_list<std::initializer_list<T>> lst)
: row{lst.size()}
, col{lst.size() ? lst.begin()->size() : 0} // Minimal validation
{
// Eliminate reallocations as we already know the size of the matrix
data.reserve(row * col);
for (auto const& r : lst) {
data.insert(data.end(), r.begin(), r.end());
}
}
};
int main() {
Matrix<double> d = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
}
So, we're saying: For each row (r) in the lst, insert the content of the row from the beginning (r.begin()) to the end (r.end()) into the end of the empty vector, data, (in an empty vector semantically we have: empty_vec.begin() == empty_vec.end()).
i might be a bit late but here is code for generally initializing tensors, regardless if they are matricies or vectors or whatever tensor.You could restrict it by throwing runtime errors when its not a matrix. Below is the source code to extract the data from the initilizer_list its a bit hacky. The whole trick is that the constructor are implicitly called with the correct type.
#include <initializer_list>
#include <iostream>
using namespace std;
class ShapeElem{
public:
ShapeElem* next;
int len;
ShapeElem(int _len,ShapeElem* _next): next(_next),len(_len){}
void print_shape(){
if (next != nullptr){
cout <<" "<< len;
next->print_shape();
}else{
cout << " " << len << "\n";
}
}
int array_len(){
if (next != nullptr){
return len*next->array_len();
}else{
return len;
}
}
};
template<class value_type>
class ArrayInit{
public:
void* data = nullptr;
size_t len;
bool is_final;
ArrayInit(std::initializer_list<value_type> init) : data((void*)init.begin()), len(init.size()),is_final(true){}
ArrayInit(std::initializer_list<ArrayInit<value_type>> init): data((void*)init.begin()), len(init.size()),is_final(false){}
ShapeElem* shape(){
if(is_final){
ShapeElem* out = new ShapeElem(len,nullptr);
}else{
ArrayInit<value_type>* first = (ArrayInit<value_type>*)data;
ShapeElem* out = new ShapeElem(len,first->shape());
}
}
void assign(value_type** pointer){
if(is_final){
for(size_t k = 0; k < len;k ++ ){
(*pointer)[k] = ( ((value_type*)data)[k]);
}
(*pointer) = (*pointer) + len;
}else{
ArrayInit<value_type>* data_array = (ArrayInit<value_type>*)data;
for(int k = 0;k < len;k++){
data_array[k].assign(pointer);
}
}
}
};
int main(){
auto x = ArrayInit<int>({{1,2,3},{92,1,3}});
auto shape = x.shape();
shape->print_shape();
int* data = new int[shape->array_len()];
int* running_pointer = data;
x.assign(&running_pointer);
for(int i = 0;i < shape->array_len();i++){
cout << " " << data[i];
}
cout << "\n";
}
outputs
2 3
1 2 3 92 1 3
The shape() function will return you the shape of the tensor at each dimension. The array is exactly saved as it is written down. It's really import to create something like shape since this will give you the ordering in which the elements are.
If you want a specific index out of the tensor lets say a[1][2][3]
the correct position is in 1*a.shape[1]a.shape[2] + 2a.shape[2] + 3
Some minor details and tricks can be found in: https://github.com/martinpflaum/multidimensional_array_cpp

C++11 reverse range-based for-loop

Is there a container adapter that would reverse the direction of iterators so I can iterate over a container in reverse with range-based for-loop?
With explicit iterators I would convert this:
for (auto i = c.begin(); i != c.end(); ++i) { ...
into this:
for (auto i = c.rbegin(); i != c.rend(); ++i) { ...
I want to convert this:
for (auto& i: c) { ...
to this:
for (auto& i: std::magic_reverse_adapter(c)) { ...
Is there such a thing or do I have to write it myself?
Actually Boost does have such adaptor: boost::adaptors::reverse.
#include <list>
#include <iostream>
#include <boost/range/adaptor/reversed.hpp>
int main()
{
std::list<int> x { 2, 3, 5, 7, 11, 13, 17, 19 };
for (auto i : boost::adaptors::reverse(x))
std::cout << i << '\n';
for (auto i : x)
std::cout << i << '\n';
}
Actually, in C++14 it can be done with a very few lines of code.
This is a very similar in idea to #Paul's solution. Due to things missing from C++11, that solution is a bit unnecessarily bloated (plus defining in std smells). Thanks to C++14 we can make it a lot more readable.
The key observation is that range-based for-loops work by relying on begin() and end() in order to acquire the range's iterators. Thanks to ADL, one doesn't even need to define their custom begin() and end() in the std:: namespace.
Here is a very simple-sample solution:
// -------------------------------------------------------------------
// --- Reversed iterable
template <typename T>
struct reversion_wrapper { T& iterable; };
template <typename T>
auto begin (reversion_wrapper<T> w) { return std::rbegin(w.iterable); }
template <typename T>
auto end (reversion_wrapper<T> w) { return std::rend(w.iterable); }
template <typename T>
reversion_wrapper<T> reverse (T&& iterable) { return { iterable }; }
This works like a charm, for instance:
template <typename T>
void print_iterable (std::ostream& out, const T& iterable)
{
for (auto&& element: iterable)
out << element << ',';
out << '\n';
}
int main (int, char**)
{
using namespace std;
// on prvalues
print_iterable(cout, reverse(initializer_list<int> { 1, 2, 3, 4, }));
// on const lvalue references
const list<int> ints_list { 1, 2, 3, 4, };
for (auto&& el: reverse(ints_list))
cout << el << ',';
cout << '\n';
// on mutable lvalue references
vector<int> ints_vec { 0, 0, 0, 0, };
size_t i = 0;
for (int& el: reverse(ints_vec))
el += i++;
print_iterable(cout, ints_vec);
print_iterable(cout, reverse(ints_vec));
return 0;
}
prints as expected
4,3,2,1,
4,3,2,1,
3,2,1,0,
0,1,2,3,
NOTE std::rbegin(), std::rend(), and std::make_reverse_iterator() are not yet implemented in GCC-4.9. I write these examples according to the standard, but they would not compile in stable g++. Nevertheless, adding temporary stubs for these three functions is very easy. Here is a sample implementation, definitely not complete but works well enough for most cases:
// --------------------------------------------------
template <typename I>
reverse_iterator<I> make_reverse_iterator (I i)
{
return std::reverse_iterator<I> { i };
}
// --------------------------------------------------
template <typename T>
auto rbegin (T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
// const container variants
template <typename T>
auto rbegin (const T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (const T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
Got this example from cppreference. It works with:
GCC 10.1+ with flag -std=c++20
#include <ranges>
#include <iostream>
int main()
{
static constexpr auto il = {3, 1, 4, 1, 5, 9};
std::ranges::reverse_view rv {il};
for (int i : rv)
std::cout << i << ' ';
std::cout << '\n';
for(int i : il | std::views::reverse)
std::cout << i << ' ';
}
If you can use range v3 , you can use the reverse range adapter ranges::view::reverse which allows you to view the container in reverse.
A minimal working example:
#include <iostream>
#include <vector>
#include <range/v3/view.hpp>
int main()
{
std::vector<int> intVec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (auto const& e : ranges::view::reverse(intVec)) {
std::cout << e << " ";
}
std::cout << std::endl;
for (auto const& e : intVec) {
std::cout << e << " ";
}
std::cout << std::endl;
}
See DEMO 1.
Note: As per Eric Niebler, this feature will be available in C++20. This can be used with the <experimental/ranges/range> header. Then the for statement will look like this:
for (auto const& e : view::reverse(intVec)) {
std::cout << e << " ";
}
See DEMO 2
This should work in C++11 without boost:
namespace std {
template<class T>
T begin(std::pair<T, T> p)
{
return p.first;
}
template<class T>
T end(std::pair<T, T> p)
{
return p.second;
}
}
template<class Iterator>
std::reverse_iterator<Iterator> make_reverse_iterator(Iterator it)
{
return std::reverse_iterator<Iterator>(it);
}
template<class Range>
std::pair<std::reverse_iterator<decltype(begin(std::declval<Range>()))>, std::reverse_iterator<decltype(begin(std::declval<Range>()))>> make_reverse_range(Range&& r)
{
return std::make_pair(make_reverse_iterator(begin(r)), make_reverse_iterator(end(r)));
}
for(auto x: make_reverse_range(r))
{
...
}
Does this work for you:
#include <iostream>
#include <list>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator_range.hpp>
int main(int argc, char* argv[]){
typedef std::list<int> Nums;
typedef Nums::iterator NumIt;
typedef boost::range_reverse_iterator<Nums>::type RevNumIt;
typedef boost::iterator_range<NumIt> irange_1;
typedef boost::iterator_range<RevNumIt> irange_2;
Nums n = {1, 2, 3, 4, 5, 6, 7, 8};
irange_1 r1 = boost::make_iterator_range( boost::begin(n), boost::end(n) );
irange_2 r2 = boost::make_iterator_range( boost::end(n), boost::begin(n) );
// prints: 1 2 3 4 5 6 7 8
for(auto e : r1)
std::cout << e << ' ';
std::cout << std::endl;
// prints: 8 7 6 5 4 3 2 1
for(auto e : r2)
std::cout << e << ' ';
std::cout << std::endl;
return 0;
}
Sorry but with current C++ (apart from C++20) all these solutions do seem to be inferior to just use index-based for. Nothing here is just "a few lines of code". So, yes: iterate via a simple int-loop. That's the best solution.
template <typename C>
struct reverse_wrapper {
C & c_;
reverse_wrapper(C & c) : c_(c) {}
typename C::reverse_iterator begin() {return c_.rbegin();}
typename C::reverse_iterator end() {return c_.rend(); }
};
template <typename C, size_t N>
struct reverse_wrapper< C[N] >{
C (&c_)[N];
reverse_wrapper( C(&c)[N] ) : c_(c) {}
typename std::reverse_iterator<const C *> begin() { return std::rbegin(c_); }
typename std::reverse_iterator<const C *> end() { return std::rend(c_); }
};
template <typename C>
reverse_wrapper<C> r_wrap(C & c) {
return reverse_wrapper<C>(c);
}
eg:
int main(int argc, const char * argv[]) {
std::vector<int> arr{1, 2, 3, 4, 5};
int arr1[] = {1, 2, 3, 4, 5};
for (auto i : r_wrap(arr)) {
printf("%d ", i);
}
printf("\n");
for (auto i : r_wrap(arr1)) {
printf("%d ", i);
}
printf("\n");
return 0;
}
You could simply use BOOST_REVERSE_FOREACH which iterates backwards. For example, the code
#include <iostream>
#include <boost\foreach.hpp>
int main()
{
int integers[] = { 0, 1, 2, 3, 4 };
BOOST_REVERSE_FOREACH(auto i, integers)
{
std::cout << i << std::endl;
}
return 0;
}
generates the following output:
4
3
2
1
0
If not using C++14, then I find below the simplest solution.
#define METHOD(NAME, ...) auto NAME __VA_ARGS__ -> decltype(m_T.r##NAME) { return m_T.r##NAME; }
template<typename T>
struct Reverse
{
T& m_T;
METHOD(begin());
METHOD(end());
METHOD(begin(), const);
METHOD(end(), const);
};
#undef METHOD
template<typename T>
Reverse<T> MakeReverse (T& t) { return Reverse<T>{t}; }
Demo.
It doesn't work for the containers/data-types (like array), which doesn't have begin/rbegin, end/rend functions.