Why didn't they add an operator version of iota? - c++

The iota template function was added to the standard library to fill an iterator range with an increasing sequence of values.
template<typename ForwardIterator, typename Tp>
void
iota(ForwardIterator first, ForwardIterator last, Tp value)
{
for (; first != last; ++first)
{
*first = value;
++value;
}
}
Most other templates in <numeric> have versions that accept user-specified operators.
Having this:
template<typename ForwardIterator, typename Tp, typename Operator>
void
iota(ForwardIterator first, ForwardIterator last, Tp value, Operator op)
{
for (; first != last; ++first)
{
*first = value;
op(value);
}
}
would be convenient if you don't want to (or can't) overload operator++() for Tp. I would find this version more widely usable than the default operator++() version.
<

I suspect the reason is the usual mix of one or more of the following reasons:
No one submitted a proposal
It wasn't considered important enough for this version (which was already huge, and very late)
it fell through the cracks and was forgotten (like copy_if in C++98)
it is easy to replace using std::generate.

With lambdas, the second version doesn't save much, you can just use std::generate.
template<typename ForwardIterator, typename Tp, typename Operator>
void iota(ForwardIterator first, ForwardIterator last, Tp value, Operator op)
{
std::generate(first, last, [&value,&op](){auto v = value; op(value); return v;});
}
In fact, this makes the existing implementation of std::iota very redundant:
template<typename ForwardIterator, typename Tp>
void iota(ForwardIterator first, ForwardIterator last, Tp value)
{
std::generate(first, last, [&value](){return value++;});
}

Related

Extract input iterator from std::copy and std::copy_n

I trying to implement an unserialization method that take an input iterator and perform a series of chunk reads (using std::copy and std::copy_n). Something like this (just an example):
template <class InputIt>
InputIt unserialize(InputIt it)
{
std::copy_n(it, sizeof(header_type), reinterpret_cast<char*>(&header));
std::copy_n(it, header.payload_size, std::back_inserter(payload));
it = optional.unserialize(it);
return it;
}
How do I advance input iterator in this case so each following call to std::copy_n continue read from it and I can finally return it?
I want to be generic to iterator categories (especially RandomAccessIterator and InputIterator) for performance reasons and hope it is possible to use std::copy methods without need to rewrite these. Stuff like bound checking and such will be done by iterator adapter or checked before unserialization call if size is known.
What do not work nor acceptable:
Using std::copy_n<InputIt&>(it, ...) may work for some categories but not for all and it's too unreliable.
Using std::advance after each call leads to rereading same block again for some iterators. Not preferable and may be impossible for some sources.
UPDATE Making iterator reference adapter doesn't help as random access iterator version of copy_n return pointer to past the last element copied while input iterator version return pointer to the last element copied. So I guess own version of copy_n works best with additional iterator adapter for bound checking.
For random access iterator this form can be used - and it is fine:
template <class InputIt, class N, class OutputIt>
InputIt copy_n_advance_input(InputIt it, N dist, OutputIt outIt)
{
std::copy_n(it, dist, outIt);
return std::next(it, dist);
}
Unfortunately - problems are when we want to deal with one pass input iterator - like here (got 'd' - not 'c'):
std::string s = "abcd";
std::istringstream ss{s};
auto e = copy_n_advance_input(std::istream_iterator<char>(ss),
2,
std::ostream_iterator<char>(std::cout, ","));
std::cout << "\n" << *e << "\n";
So it seems it is needed, as usual in STL, two forms:
template <class InputIt, class N, class OutputIt>
InputIt copy_n_advance_input_impl(InputIt it, N dist, OutputIt outIt,
std::input_iterator_tag)
{
while (dist-- > 0)
{
*outIt = *it;
++outIt;
++it;
}
return it;
}
template <class InputIt, class N, class OutputIt>
InputIt copy_n_advance_input_impl(InputIt it, N dist, OutputIt outIt,
std::random_access_iterator_tag)
{
std::copy_n(it, dist, outIt);
return std::next(it, dist);
}
template <class InputIt, class N, class OutputIt>
InputIt copy_n_advance_input(InputIt it, N dist, OutputIt outIt)
{
return copy_n_advance_input_impl(it, dist, outIt, typename std::iterator_traits<InputIt>::iterator_category {});
}
Note, the proposed version for std::input_iterator_tag is not as efficient as in STL (at least for gcc) - it does extra iteration for input - this iteration is not necessary to perform copy - but it is needed to return beginning of "after copy" range (stl_algo.h):
754 template<typename _InputIterator, typename _Size, typename _OutputIterator>
755 _OutputIterator
756 __copy_n(_InputIterator __first, _Size __n,
757 _OutputIterator __result, input_iterator_tag)
758 {
759 if (__n > 0)
760 {
761 while (true)
762 {
763 *__result = *__first;
764 ++__result;
765 if (--__n > 0)
766 ++__first;
767 else
768 break;
769 }
770 }
771 return __result;
772 }
Last note - it is wiser to use, for random-access-iterators (like std::vector::iterator) the version that just calls std algorithms - because they can be even more optimized - e.g. for contiguous memory iterator over POD types - that can be just memcpy'ied. Or some specialization for std::vector<bool> or std::deque<T> exist, that uses their internal structure to perform copy in most efficient way.
You could create an iterator adapter that always works through a reference to the supplied iterator. Here's the basic skeleton of such an adapter:
#include <iterator>
template<typename InputIterator>
struct IteratorReference
{
InputIterator& it;
IteratorReference(InputIterator& it)
: it(it)
{}
// {copy, move, destructor} == default
// iterator methods (TODO: add the rest)
IteratorReference& operator++()
{ ++it; return this; }
typename InputIterator::reference operator*()
{ return *it; }
// Convert back to original iterator
operator InputIterator() const
{ return it; }
};
template<typename InputIterator>
IteratorReference<InputIterator> make_iterator_reference(InputIterator it)
{
return it;
}
To use it, simply create and use a wrapper in place of the original iterator:
#include <algorithm>
#include <vector>
struct Header
{
std::size_t payload_size;
};
template <class InputIt>
InputIt unserialize(InputIt it, Header& header, std::vector<char>& payload)
{
auto i_ref = make_iterator_reference(it);
std::copy_n(i_ref, sizeof header, reinterpret_cast<char*>(&header));
std::copy_n(i_ref, header.payload_size, std::back_inserter(payload));
i_ref = optional.unserialize(i_ref);
return i_ref;
}
I know this is an old question, but...
Recently I've run into similar issue, and I feel pretty sad when I see there isn't any good solution for this problem...
Nevertheless, I've tried to write an iterator wrapper like what Toby Speight said, and I've extended it a bit.
This wrapper is only used for InputIterator, because other kind of iterators supported by std::copy and std::copy_n are multipass iterators, and it's possible to directly use std::next and std::advance on them instead of using this wrapper.
template<typename Iterator>
struct Wrapper {
using traits = std::iterator_traits<Iterator>;
using difference_type = typename Traits::difference_type;
using reference = typename Traits::reference;
//...
reference operator*() const { return *(*(this->current)); }
//need implement operator++(int) too, in the similar way
Wrapper& operator++() {
if(this->indicator != 0) {
++(*(this->current));
--this->indicator;
}
return *this;
}
//need to implement operator!= too, in the similar way
bool operator==(const Wrapper& other) const {
return *(this->current) == *(other.current) or this->indicator == other.indicator;
}
Iterator* current;
difference_type indicator;
};
template<typename Iterator>
struct Range {
using category = typename std::iterator_traits<Iterator>::iterator_category;
//...
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
constexpr bool isForwardOrAbove() {
return std::is_base_of_v<std::forward_iterator_tag, category>;
}
using iterator = std::conditional_t<isForwardOrAbove(), Iterator, Wrapper<Iterator>>;
std::pair<iterator, iterator> splitSubRange(difference_type n) {
if constexpr (isForwardOrAbove()) {
//forward iterators are multi-pass iterators, so using std::advance on one iterator will not invalidate its copies
auto oldBegin = this->begin;
std::advance(this->begin, n);
return {oldBegin, std::next(oldBegin, n)};
}
else {
//non-forward-iterator
return {{&(this->begin), n}, {&(this->end), 0}};
}
}
Iterator begin;
Iterator end;
}
To use them, firstly you need a Range object which holds iterators, and use the splitSubRange method to obtain plain iterators, or, if they are only InputIterators, iterator wrappers.
template<typename InputIterator>
InputIterator unserialize(InputIterator begin, InputIterator end) {
auto range = Range<InputIterator>{begin, end};
auto [begin, end] = range.splitSubRange(sizeof(header_type));
//before having "used" the iterator obtained from range, you shouldn't use range again.
std::copy(begin, end, header.begin());
//after having "used" the iterator, you can use the range object to obtain the next sub-range
auto [begin2, dummy] = range.splitSubRange(sizeof(header_type_2));
std::copy_n(begin2, sizeof(header_type_2), header2.begin());
...
return range.begin;
}

How to avoid to declare the same type two different times in function header and body when dealing with templates?

I wrote this function that returns the mean of the values in the range delimited by two iterators:
template<class InputIterator>
typename std::decay<decltype(*std::declval<InputIterator>())>::type mean (InputIterator first, InputIterator last) {
return std::accumulate(first, last, typename std::decay<decltype(*std::declval<InputIterator>())>::type ()) / std::distance(first, last);
}
The value type, which is both used internally and returned, is deduced from the iterator. Since the syntax for the type deduction is quite heavy I was wondering if there is a way to avoid to use it twice.
I know that I may add a second template parameter and set its default to the value type, but I'm not convinced since one may specify a different value type and I would like to preclude this possibility.
You can use alias templates to form a generic typedef for yourType
template<class InIt>
using yourType = typename decay<decltype(*declval<InIt>())>::type;
template<class InIt>
yourType<InIt> mean(InIt first, InIt last)
{
return accumulate(first, last, yourType<InIt>()) / distance(first, last);
}
Live Demo
To avoid user to change the default type, you may add a variadic tamplate
template <typename InputIterator,
typename...,
typename Type = typename std::decay<decltype(*std::declval<InputIterator>())>::type
>
Type mean (InputIterator first, InputIterator last) {
return std::accumulate(first, last, Type()) / std::distance(first, last);
}
or even more secure to avoid to provide more template argument to mean.
template <typename InputIterator,
typename...DummyTs,
typename Type = typename std::decay<decltype(*std::declval<InputIterator>())>::type,
typename = typename std::enable_if<sizeof...(DummyTs) == 0>::type
>
Type mean (InputIterator first, InputIterator last) {
return std::accumulate(first, last, Type()) / std::distance(first, last);
}

Implementations of count_until and accumulate_until?

Given an input sequence, the standard algorithms std::count and std::accumulate count the number of occurances of a specific value (or predicate matches for std::count_if) and the accumulation of a given associative operation (sum, product, Boolean or/and, min/max, string concatenation, etc.), respectively.
What if one wants to know whether an input sequence contains exactly/at least/at most n occurances/matches, or accumulates to a sum of exactly/at least/at most n? The brute-force way would be to compare the result of std::count or std::accumulate against the target n, but that would miss out on an early exit opportunity when the count or accumulation exceeds the target already halfway through the input sequence.
One could e.g. make a count_until as
template<class InputIt, class T, class Pred>
auto count_until(InputIt first, InputIt last, const T& value, Pred pred)
{
auto res = 0;
for (; first != last; ++first)
if (*first == value && pred(++res))
break; // early exit if predicate is satisfied
return std::make_pair(first, res); // iterator and value to allow continuation
}
and from which one could test for equality/at least/at most by using a suitable predicate and comparison against the returned count.
Questions:
is it possible to write count_until (and similarly for accumulate_until) using a combination existing standard algorithms, possibly in combination with a suitable Boost.Iterator?
In particular, I was thinking of a find_if over an accumulate_iterator where the predicate would extract the count or sum from the iterator.
Or do count_until and accumulate_until warrant inclusion as standalone primitives in a future version of the Standard Library?
Edit: I think the most useful formulation is to return a std::pair of an iterator and the count at the point where the predicate is first satisfied. This enables users to continue iterating.
I was thinking of a combination of std::find_if with a state predicate:
(Pred is normal user predicate.)
template<class InputIt, class T, class Pred>
typename iterator_traits<InputIterator>::difference_type
count_until(InputIt begin, InputIt end, const T& value, Pred pred)
{
typename iterator_traits<InputIterator>::difference_type count = 0;
auto internal_pred = [&count, &value, &pred](decltype(*begin) elem) {
return elem == value && pred(++count);
};
std::find_if(begin, end, internal_pred);
return count;
}
template<class InputIt, class T, class Pred>
T accumulate_until(InputIt begin, InputIt end, T value, Pred pred)
{
auto internal_pred = [&value, &pred] (const T& t) {
value += t;
return pred(value);
};
std::find_if(begin, end, internal_pred);
return value;
}

Get all vector elements that don't belong to another vector

In C# if I want to get all elements in a List List1, which don't belong to another List List2 I can do
var result List1.Except(List2);
Is there something equivalent for std::vectors in C++? (C++11 is allowed)
The following populates List3 with the content from List1 that is not in List2. I hope it is what you're looking for:
std::vector<Type> List1, List2;
//
// populate List1 and List2
//
std::vector<Type> List3;
std::copy_if(List1.begin(), List1.end(), std::back_inserter(List3),
[&List2](const Type& arg)
{ return (std::find(List2.begin(), List2.end(), arg) == List2.end());});
Alternatively, this is likely better performing, since you don't have to search the entire list to determine lack of existence. Rather you can get an early "hit" and just move to the next node. Note the logic flip in the predicate:
std::vector<Type> List3;
std::remove_copy_if(List1.begin(), List1.end(), std::back_inserter(List3),
[&List2](const Type& arg)
{ return (std::find(List2.begin(), List2.end(), arg) != List2.end());});
You need to write your own function something like this:
for (auto element : List1)
{
auto it = std::find(List2.begin(), List2.end(), element);
if(it == List2.end())
{
result.push_back(element);
}
}
You should consider if a std::list is the right data structure for that, as it is - at least in C++ - not sorted by default, so in the worst case you will have to iterate size(list2) times through all elements of the list1, using an algorithm like Asha pointed out.
A better approach would be the use of an ordered container, e.g. multiset and use std::set_difference to create a result.
For any arbitrary container you can always use the std::remove_if + container::erase combination:
template <typename Cont, typename FwdIt>
void subtract(Cont& cont, FwdIt first, FwdIt last) {
using std::begin; using std::end;
using const_reference = typename Cont::value_type const&;
cont.erase(std::remove_if(begin(cont), end(cont),
[first, last](const_reference value){
return last != std::find(first, last, value);
}), end(cont));
}
template <typename Cont1, typename Cont2>
void subtract(Cont1& cont1, Cont2 const& cont2) {
using std::begin; using std::end;
subtract(cont1, begin(cont2), end(cont2));
}
In the case of std::list you can overload the subtract function, because std::list has a dedicated remove_if member function:
template <typename T, typename Alloc, typename FwdIt>
void subtract(std::list<T, Alloc>& l, FwdIt first, FwdIt last) {
l.remove_if([first, last](T const& value){
return last != std::find(first, last, value);
});
}
template <typename T, typename Alloc, typename Cont>
void subtract(std::list<T, Alloc>& l, Cont const& cont) {
using std::begin; using std::end;
subtract(l, begin(cont), end(cont));
}
These implementation are generic and make no assumption about the sorting of the sequences.
If only your second container is guaranteed to be sorted, you can use std::binary_seach instead of find.
If both sequences are sorted, you should use std::set_difference.

How to check that the passed Iterator is a random access iterator?

I have the following code, which does some iterator arithmetic:
template<class Iterator>
void Foo(Iterator first, Iterator last) {
typedef typename Iterator::value_type Value;
std::vector<Value> vec;
vec.resize(last - first);
// ...
}
The (last - first) expression works (AFAIK) only for random access iterators (like the ones from vector and deque). How can I check in the code that the passed iterator meets this requirement?
If Iterator is a random access iterator, then
std::iterator_traits<Iterator>::iterator_category
will be std::random_access_iterator_tag. The cleanest way to implement this is probably to create a second function template and have Foo call it:
template <typename Iterator>
void FooImpl(Iterator first, Iterator last, std::random_access_iterator_tag) {
// ...
}
template <typename Iterator>
void Foo(Iterator first, Iterator last) {
typedef typename std::iterator_traits<Iterator>::iterator_category category;
return FooImpl(first, last, category());
}
This has the advantage that you can overload FooImpl for different categories of iterators if you'd like.
Scott Meyers discusses this technique in one of the Effective C++ books (I don't remember which one).
In addition to the tag dispatch, you can compare the category to std::random_access_iterator_tag directly using std::is_same_v:
using category = typename std::iterator_traits<Iterator>::iterator_category;
if constexpr (std::is_same_v<category, std::random_access_iterator_tag>) {
vec.resize(last - first);
}
This can sometimes lead to a more clear and concise code, particularly if only a small part of your implementation (like reserving the vector size) depends on the iterator category.