If I have a function
std::array<unsigned,2> fib(std::array<unsigned,2> p)
{
return {p[1],p[1]+p[0]};
}
I'd like to have a way to elegantly generate the infinite range
[x,fib(x),fib(fib(x)),fib(fib(fib(x))),...]
This comes up frequently enough that I need to find what's the best way to do this?
I found that the generator from this repo works well:
template<typename F, typename Arg>
tl::generator<Arg> iterated_application(F fn, Arg x) {
while (true) {
co_yield x;
x = fn(x);
}
}
Which can be used as
int main()
{
auto fib = [](auto a) {return std::array{ a[1],a[1] + a[0] }; };
for (auto i : iterated_application(fib, std::array{ 0,1 })
| std::views::keys
| std::views::take(10))
std::cout << i << std::endl;
}
https://godbolt.org/z/v73zvY9cM
You could always create your own iterator:
template<typename Arg>
struct impl_iterated_application {
using value_type = Arg;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
const Arg& operator*() const { return current; }
impl_iterated_application& operator++()
{
current = fn(current);
return *this;
}
auto operator++(int) { auto temp = *this; ++* this; return temp; }
impl_iterated_application(std::function<Arg(Arg)> f = std::identity{}, Arg initial = {}) : current(initial), fn(f)
{}
//bool operator==(const impl_iterated& other) const = default;
private:
Arg current;
std::function<Arg(Arg)> fn;
};
which you would use in this factory function:
template<typename F, typename Arg>
auto iterated_application(F fn, Arg x)
{
return std::ranges::subrange(impl_iterated_application(std::function<Arg(Arg)>{fn}, x), std::unreachable_sentinel);
}
https://godbolt.org/z/dxvn54ffv
I think co-routine generators are be the way to do this. I should try to get https://github.com/lewissbaker/cppcoro working.
I guess you could be a bit abusive and use partial sum, ignoring all but the first element in the adapted range:
auto fib = ranges::views::repeat(std::array{ 0,1 })
| ranges::views::partial_sum([](auto a, auto){ return std::array{ a[1], a[0] + a[1] }; });
for (auto elem : fib | ranges::views::take(10))
std::cout << elem[0] << std::endl;
A mutable lambda also works
template<typename Arg, std::invocable<Arg> F>
auto iterated_application(F fn, Arg x)
{
return ranges::views::generate(
[p = x, f=fn]() mutable
{
auto p0 = p;
p = f(p);
return p0;
});
}
Related
Tuple foreach is relatively simple using either recursion or std::apply:
#include <cstring>
#include <iostream>
#include <tuple>
#include <utility>
template<typename F, typename T>
auto foreach_apply(F&& f, T &&t) {
return std::apply([&f](auto&&... elements) {
return (f(std::forward<decltype(elements)>(elements)) || ...);
}, std::forward<T>(t));
}
template <std::size_t I=0, typename F, typename... Ts>
void foreach_recurse(F&& f, std::tuple<Ts...> t) {
if constexpr (I == sizeof...(Ts)) {
return;
} else {
f(std::get<I>(t));
find<I+1>(f, t);
}
}
int main() {
//auto a = std::tuple(true, true, false, false, true);
auto a = std::tuple("one", "two", "three", "four", "five");
//auto b = foreach_recurse([](auto& element) -> bool {
auto b = foreach_apply([](auto& element) -> bool {
std::cout << element << std::endl;
if (!strcmp("three", element))
return true;
else
return false;
}, a);
std::cout << "Done" << std::endl;
std::cout << b << std::endl << std::endl;
}
Indexing is only slightly trickier:
template <std::size_t I=0, typename F, typename... Ts>
size_t index_recurse(F&& f, std::tuple<Ts...> t) {
if constexpr (I == sizeof...(Ts)) {
return -1;
} else {
auto e = std::get<I>(t);
if (f(e))
return I;
return index_recurse<I+1>(f, t);
}
}
template <std::size_t I=0, typename F, typename... Ts>
bool index_recurse_2(F&& f, std::tuple<Ts...> t, size_t* i) {
if constexpr (I == sizeof...(Ts)) {
return false;
} else {
auto e = std::get<I>(t);
if (f(e)) {
*i = I;
return true;
}
return index_recurse_2<I+1>(f, t, i);
}
}
template<typename F, typename T>
auto index_apply(F&& f, T &&t, size_t* ix) {
return std::apply([&f,ix] (auto&&... elements) {
return [&f,ix]<std::size_t... I>(std::index_sequence<I...>, auto&&... elements) {
auto fi = [&f,ix](auto i, auto&& element) {
auto r = f(std::forward<decltype(element)>(element));
if (r)
*ix = i;
return r;
};
return (fi(I, std::forward<decltype(elements)>(elements)) || ...);
}
( std::make_index_sequence<sizeof...(elements)>()
, std::forward<decltype(elements)>(elements)...
);
}, std::forward<T>(t));
}
int main() {
/*
auto a = std::tuple("one", "two", "three", "four", "five");
auto b = index_recurse([](auto& element) -> bool {
std::cout << element << std::endl;
if (!strcmp("three", element))
return true;
else
return false;
}, a);
std::cout << "Done" << std::endl;
std::cout << b << std::endl << std::endl;
*/
/*
auto a = std::tuple("one", "two", "three", "four", "five");
size_t b;
auto c = index_recurse_2([](auto& element) -> bool {
std::cout << element << std::endl;
if (!strcmp("three", element))
return true;
else
return false;
}, a, &b);
std::cout << "Done" << std::endl;
std::cout << b << std::endl << std::endl;
*/
/*
auto a = std::tuple("one", "two", "three", "four", "five");
size_t b;
auto c = index_apply([](auto& element) -> bool {
std::cout << element << std::endl;
if (!strcmp("three", element))
return true;
else
return false;
}, a, &b);
std::cout << "Done" << std::endl;
std::cout << b << std::endl << std::endl;
*/
}
Now, get the value rather than the index. The index_* functions show that this is possible. We take a compile-time value (tuple) and a set of compile-time functions (unrolled index functions), apply a runtime function that matches an input, and get a runtime value that depends on the compile-time values. This is what the find_* functions attempt to do.
Given a tuple T of length N, find_broken_1 unrolls to N functions of type (i:0-N, T) where each function either returns the i-th function, or returns from the next in the sequence. That means the return type of the i-th function must match all the previous return types. So this recursive approach can't work.
template <std::size_t I=0, typename F, typename... Ts>
auto* find_broken_1(F&& f, std::tuple<Ts...> t) {
if constexpr (I == sizeof...(Ts)) {
// What type? Can this be fixed?
return (const char**)&"<>";
//return (void*)nullptr;
//return ((decltype(std::get<I-1>)::type)*)nullptr;
} else {
auto& e = std::get<I>(t);
if (f(e))
return &e;
std::cout << e << std::endl;
return find_broken_1<I+1>(f, t);
}
}
Here index is not known at compile-time so std::get won't compile. It would be nice if C++ would template for every possible index so this would work during runtime, just like C++ already unrolls every possible index function.
template <typename F, typename T>
auto find_broken_2(F&& f, T&& t, bool* b) {
const size_t i = index_recurse(f, t);
if (i >= 0) {
*b = true;
return std::get<i>(t);
}
else {
*b = false;
//return nullptr;
}
}
We know we can generate a runtime value from a compile-time value. If the transform is reversible and the bounds are known, we should be able to lookup a compile-time value from a runtime value. How can we trick the compiler into doing so? Then integrate this into the index_* functions to avoid double iteration.
Moving something into a type forces it to become a compile-time something. Unfortunately this unrolls to a different return type for each generated function, and since the returns are chained, generates a compile error. Once again, the recursive approach fails.
I'm just trying a bunch of different ideas, none working:
template<bool value, typename ...>
struct bool_type : std::integral_constant<bool , value> {};
//std::integral_constant<int, I> run_to_compile(size_t i, std::tuple<Ts...> t) {
template <std::size_t I=0, typename... Ts>
auto run_to_compile(size_t i, std::tuple<Ts...> t) {
if constexpr (I == sizeof...(Ts)) {
return std::integral_constant<int, I-1>();
// replace with static_assert... nope
//static_assert(bool_type<false, Ts...>::value, "wrong");
//return I-1;
}
else {
//if (i == I) {
if (I > 2) {
//return;
return std::integral_constant<int, I>();
//return I;
}
return run_to_compile<I+1>(i, t);
}
}
template<int value, typename ...>
struct int_type : std::integral_constant<int , value> {};
template <int I=0, typename T>
constexpr auto run_to_compile_2(int i) {
return int_type<i, T>();
}
template <typename F, typename T>
auto find_broken_3(F&& f, T&& t, bool* b) {
const size_t ir = index_recurse(f, t);
// nope
//constexpr decltype(t) temp = {};
// nope, again (really?)
//auto ic = std::integral_constant<int, ir>();
//constexpr auto ic = run_to_compile(0, temp);
//const auto ic = run_to_compile(ir, t);
//const auto ic = r2c_2<const int>(ir);
run_to_compile_2<2, int>(2);
const auto ic = 2;
if (ir >= 0) {
*b = true;
return std::get<ic>(t);
}
else {
*b = false;
//return nullptr;
}
}
How can I fix this?
Return type cannot depend of runtime. So a possibility to unify the return type is std::variant:
template <typename F, typename... Ts>
auto find_in_tuple(F&& f, std::tuple<Ts...> t)
{
std::optional<std::variant<Ts...>> res;
std::apply([&](auto&&... args){
auto lambda = [&](auto&& arg){
if (!res && f(arg))
res = arg;
};
(lambda(args), ...);
}, t);
return res;
}
Demo
I have the following code to generate tuples of adjacent pairs in a range. This works for bidirectional ranges but not for forward only ranged.
template <typename Range>
// Returns a range of adjacent pairs of the input range
auto make_adjacent_range(Range const & r) -> decltype(boost::combine(
boost::make_iterator_range(boost::begin(r), boost::prior(boost::end(r))),
boost::make_iterator_range(boost::next(boost::begin(r)), boost::end(r))))
{
return boost::combine(
boost::make_iterator_range(boost::begin(r), boost::prior(boost::end(r))),
boost::make_iterator_range(boost::next(boost::begin(r)), boost::end(r)));
}
boost::prior is not accepted with a forward only range. Is there an equally elegant solution that will work with forward ranges?
boost::combine
Not really elegant, but you can just write a adjacent_iterator type.
It's relatively tricky to get it to work for InputIterator, as you have to dereference before each increment
template <typename InputIterator>
class adjacent_iterator
{
public:
using element_type = std::iterator_traits<InputIterator>::value_type;
using value_type = std::pair<element_type, element_type>;
using category = std::iterator_traits<InputIterator>::category;
// all the other typedefs
adjacent_iterator& operator++()
{
element.first = element.second;
if (needs_deref) element.second = *it;
++it;
needs_deref = true;
return *this;
}
reference operator*()
{
element.second = *it;
needs_deref = false;
return element;
}
// all the other members
friend bool operator==(adjacent_iterator lhs, adjacent_iterator rhs)
{
// only check the iterator
return lhs.it == rhs.it;
}
private:
adjacent_iterator(element_type first, InputIterator second)
: element(first, {}), it(second), needs_deref(true) {}
adjacent_iterator(InputIterator end)
: it(end) {}
InputIterator it;
value_type element;
bool needs_deref;
// not sure how to declare this friendship
template <typename Range>
friend auto make_adjacent_range(Range const & r)
{
auto begin = boost::begin(r);
auto end = boost::end(r);
using IT = decltype(boost::begin(r));
auto elem = *begin++;
auto b = adjacent_iterator<IT>(elem, begin);
auto e = adjacent_iterator<IT>(end);
return boost::make_iterator_range(b, e);
}
};
This works, but could be quite inefficient depending on the iterator types:
template <typename Range>
auto make_adjacent_range(Range const & r) {
auto n = boost::size(r);
auto b = boost::begin(r);
auto r1 = boost::make_iterator_range(b, boost::next(b, n-1));
auto r2 = r1;
r2.advance_begin(1);
r2.advance_end(1);
return boost::combine(r1, r2);
}
Live On Coliru
#include <boost/range.hpp>
#include <boost/range/combine.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <iostream>
#include <forward_list>
template <typename Range>
auto make_adjacent_range(Range const & r) {
auto n = boost::size(r);
auto b = boost::begin(r);
auto r1 = boost::make_iterator_range(b, boost::next(b, n-1));
auto r2 = r1;
r2.advance_begin(1);
r2.advance_end(1);
return boost::combine(r1, r2);
}
int main() {
std::forward_list<int> v{1,2,3,4};
for (auto p : make_adjacent_range(v))
std::cout << p.get<0>() << " " << p.get<1>() << "\n";
}
Prints
1 2
2 3
3 4
Perhaps it would be nicer to make an iterator adaptor.
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
We have some "iterable" collection of data, for instance: std::vector<Foo> bar.
We wish to process Foo elements from bar until some condition is met in which point we "yield" (think Python) the result of all these processed Foos and wait until the next chunk of parsed information is requested.
So far what we're doing is this:
ParsedChunk foobar( std::vector<Foo> bar, size_t* start_from) {
size_t& i = *start_from;
ParsedChunk result_so_far;
for (;i < bar.size(); i++) {
process_some_foo_and_update_chunk(result_so_far, bar[i]);
if (check_condition(? ? ?) {
return result_so_far;
}
}
}
Any suggestions for doing this better?
As I already pointed out in my comment, this is IMO a very good case for an custom iterator:
The iterator scans through your range, as long as some predicate holds, and
when the predicate isn't true for some element, calls a function with the sub range of elements where the predicate held (plus the one that didn't satisfy the predicate). The result of that function call is then the value you get when you dereference the iterator.
template<typename Fn, typename Predicate, typename Iterator>
struct collector {
using value_type = typename std::result_of<Fn(Iterator, Iterator)>::type;
using pointer = value_type const *;
using reference = value_type const &;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
value_type cache;
Fn fn;
Predicate predicate;
Iterator pos, from, stop;
collector(Fn&& fn, Predicate&& p, Iterator&& s, Iterator&& e)
: fn(std::forward<Fn>(fn)),
predicate(std::forward<Predicate>(p)),
pos(std::forward<Iterator>(s)),
from(pos),
stop(std::forward<Iterator>(e))
{
next_range();
}
collector & operator++(void) {
next_range();
return *this;
}
reference operator*(void) const {
return cache;
}
void next_range(void) {
from = pos;
if (pos == stop) return;
for (; pos != stop; ++pos) {
if (not predicate(*pos)) {
++pos;
break;
}
}
cache = fn(from, pos);
}
collector end_of_range(void) const {
auto copy = collector{*this};
copy.pos = copy.stop;
copy.from = copy.stop;
return copy;
}
bool operator==(collector const & rhs) const {
return (from == rhs.from) and (pos == rhs.pos) and (stop == rhs.stop);
}
bool operator!=(collector const & rhs) const {
return (from != rhs.from) or (pos != rhs.pos) or (stop != rhs.stop);
}
};
template<typename Fn, typename Predicate, typename Iterator>
auto make_collector_range(Fn&& fn, Predicate&& p, Iterator&& s, Iterator&& e) {
using I = typename std::decay<Iterator>::type;
using P = typename std::decay<Predicate>::type;
using F = typename std::decay<Fn>::type;
using C = collector<F,P,I>;
auto start = C{
std::forward<Fn>(fn), std::forward<Predicate>(p),
std::forward<Iterator>(s), std::forward<Iterator>(e)};
auto stop = start.end_of_range();
return make_pair(std::move(start), std::move(stop));
}
An example usage, calculating the sum of the numbers till 50, but not in one step, but in steps of 15 numbers each:
int main(int, char**) {
vector<int> numbers = vector<int>(50);
generate(begin(numbers), end(numbers),
[i = 0] (void) mutable{
return ++i;
});
copy(begin(numbers), end(numbers), ostream_iterator<int>{cout, " "});
cout << endl;
auto collected = make_collector_range(
[](auto const & from, auto const & to) {
return accumulate(from, to, 0);
},
[](auto const & num) {
return not ((num % 3 == 0) and (num % 5 == 0));
},
begin(numbers), end(numbers));
copy(collected.first, collected.second, ostream_iterator<int>{cout, " "});
cout << endl;
bool passed = accumulate(collected.first, collected.second, 0) == (50*51)/2;
cout << "test " << (passed ? "passed" : "failed") << endl;
return 0;
}
(Live demo here)
(Note: This example uses a fixed "step" width, and predicate and function are unrelated to each other and don't maintain state, but none of this is required by the iterator.)
I hope the intention of the code is clear, if not I can try to provide a more detailed explanation about its workings.
I'm wondering: is there any possibility to add additional condition to for each?
I'm thinking about something like:
int i=0;
for(auto &it : list; i++)
if(it.ID == 25)
return i;
or
for(auto &it : list, int i=0; i++)
if(it.ID == 25)
return i;
You can use std::find_if:
const auto position = std::find_if(list.cbegin(), list.cend(), []((decltype(*list.cbegin()) value)
{
return value.ID == 25;
});
return position - list.cbegin();
(Updated, now independent of container value_type)
No it's not possible. You can use the old "normal" for loop for that:
auto iter = std:begin(list)
for (int i = 0; iter != std::end(list); ++iter, ++i)
{
auto& it = *iter;
// ...
}
Mandatory Reference: Sean Parent's "Seasoning C++" talk:
goal 1: Avoid raw loops
In cases like these, abstract your algorithm!
This will come up more often, so it's worth making it generic:
#include <algorithm>
template <typename C, typename Pred>
size_t index_if(C const& c, Pred&& pred)
{
const auto f(begin(c)), l(end(c));
auto match = std::find_if(f, l, std::forward<Pred>(pred));
return (l==match) ? -1 : std::distance(f, match);
}
Now you can write your query:
int main()
{
struct X { int ID; };
const std::vector<X> v { {1},{2},{3},{25},{4},{5},{6},{42} };
return index_if(v, [](X const& x) { return x.ID == 25; });
}
See it Live on Coliru
PS. You might want a value-based version along with the predicate-based one:
template <typename C, typename V/* = typename C::value_type*/>
size_t index_of(C const& c, V const v)
{
const auto f(begin(c)), l(end(c));
auto match = std::find(f, l, v);
return (l==match) ? -1 : std::distance(f, match);
}