Disclaimer: I have no prior experience in implementing iterators or in C++20
This seems to work for me with gcc 10.1 and -std=c++2a
. I put this together in very short time without putting much thought into it, so the implementation can certainly be improved, if only by templatizing it. If operator<=>
is exchanged for the old two-way comparison operators, this should also run with C++17, but I haven't tested it. If you find any errors or easily correctable design flaws, you are welcome to comment them below, such that this answer can be improved.
#include <cstddef>
#if __cplusplus > 201703L
#include <compare>
#endif
#include <execution>
#include <iostream>
#include <iterator>
#include <numeric>
class counting_iterator {
public:
typedef std::ptrdiff_t difference_type;
typedef std::ptrdiff_t value_type;
typedef void pointer;
typedef void reference;
typedef std::random_access_iterator_tag iterator_category;
private:
value_type val_{0};
public:
counting_iterator() = default;
explicit counting_iterator(value_type init) noexcept : val_{init} {}
value_type operator*() const noexcept { return val_; }
value_type operator[](difference_type index) const noexcept {
return val_ + index;
}
counting_iterator &operator++() noexcept {
++val_;
return *this;
}
counting_iterator operator++(int) noexcept {
counting_iterator res{*this};
++(*this);
return res;
}
counting_iterator &operator--() noexcept {
--val_;
return *this;
}
counting_iterator operator--(int) noexcept {
counting_iterator res{*this};
--(*this);
return res;
}
friend counting_iterator operator+(counting_iterator const &it,
difference_type const &offset) noexcept;
friend counting_iterator operator+(difference_type const &offset,
counting_iterator const &it) noexcept;
friend counting_iterator operator-(counting_iterator const &it,
difference_type const &offset) noexcept;
friend difference_type operator-(counting_iterator const &a,
counting_iterator const &b) noexcept;
counting_iterator &operator+=(difference_type offset) noexcept {
val_ += offset;
return *this;
}
counting_iterator &operator-=(difference_type offset) noexcept {
val_ -= offset;
return *this;
}
friend bool operator==(counting_iterator const &a,
counting_iterator const &b) noexcept;
#if __cplusplus > 201703L
friend std::strong_ordering operator<=>(counting_iterator const &a,
counting_iterator const &b);
#else
friend bool operator!=(counting_iterator const &a,
counting_iterator const &b) noexcept;
friend bool operator<=(counting_iterator const &a,
counting_iterator const &b) noexcept;
friend bool operator>=(counting_iterator const &a,
counting_iterator const &b) noexcept;
friend bool operator<(counting_iterator const &a,
counting_iterator const &b) noexcept;
friend bool operator>(counting_iterator const &a,
counting_iterator const &b) noexcept;
#endif
};
counting_iterator
operator+(counting_iterator const &it,
counting_iterator::difference_type const &offset) noexcept {
return counting_iterator{it.val_ + offset};
}
counting_iterator operator+(counting_iterator::difference_type const &offset,
counting_iterator const &it) noexcept {
return counting_iterator{it.val_ + offset};
}
counting_iterator
operator-(counting_iterator const &it,
counting_iterator::difference_type const &offset) noexcept {
return counting_iterator{it.val_ - offset};
}
counting_iterator::difference_type
operator-(counting_iterator const &a, counting_iterator const &b) noexcept {
return a.val_ - b.val_;
}
bool operator==(counting_iterator const &a,
counting_iterator const &b) noexcept {
return a.val_ == b.val_;
}
#if __cplusplus > 201703L
std::strong_ordering operator<=>(counting_iterator const &a,
counting_iterator const &b) {
return a.val_ <=> b.val_;
}
#else
bool operator!=(counting_iterator const &a,
counting_iterator const &b) noexcept {
return a.val_ != b.val_;
}
bool operator<=(counting_iterator const &a,
counting_iterator const &b) noexcept {
return a.val_ <= b.val_;
}
bool operator>=(counting_iterator const &a,
counting_iterator const &b) noexcept {
return a.val_ >= b.val_;
}
bool operator<(counting_iterator const &a,
counting_iterator const &b) noexcept {
return a.val_ < b.val_;
}
bool operator>(counting_iterator const &a,
counting_iterator const &b) noexcept {
return a.val_ > b.val_;
}
#endif
int main() {
auto res = std::transform_reduce(
std::execution::par,
counting_iterator(0), counting_iterator(10),
0L,
std::plus<>(),
[](const std::ptrdiff_t& i) { return i * i; });
std::cout << res << std::endl;
}
EDIT: I worked over the class to make it usable with C++17 as well. Now it also explicitly typedefs the std::random_access_iterator_tag
. I still don't get any parallel computing with that execution policy, neither with the iterator nor with the vector, so I don't know if there is anything about the class itself inhibiting parallel execution.