C++ confused with partial template specialization syntax - c++

Is there a way I could avoid using Range2 as a name and have both classes named Range? I'm a bit confused with the C++ template syntax.
template <int BEGIN, int END>
class Range2
{
public:
class Iterator
{
private:
int n;
public:
Iterator(int n)
: n(n)
{
}
int operator *() const
{
return n;
}
Iterator const & operator ++()
{
++n;
return *this;
}
bool operator !=(Iterator const & i) const
{
return n != i.n;
}
};
Iterator begin() const
{
return Iterator(BEGIN);
}
Iterator end() const
{
return Iterator(END);
}
};
template<int END>
class Range
: public Range2<0, END>
{
};

As with function arguments, in C++ template arguments can have a default value. The only thing you will have to pay for this putting the END, which has no default value, before the BEGIN, which has 0 as default.
// Here we add the default parameter to BEGIN
// The arguments are switched because END is without a default
// parameter, so it has to come before BEGIN that has one
template <int END, int BEGIN=0>
// The class itself is the same, but now you can use it
// without giving a BEGIN parameters
class Range
{
public:
class Iterator
{
private:
int n;
public:
Iterator(int n)
: n(n)
{
}
int operator *() const
{
return n;
}
Iterator const & operator ++()
{
++n;
return *this;
}
bool operator !=(Iterator const & i) const
{
return n != i.n;
}
};
Iterator begin() const
{
return Iterator(BEGIN);
}
Iterator end() const
{
return Iterator(END);
}
};
It compiles and should work as intended. Without a main, I wasn't able to test it, though.
EDIT: I added some comments and here an example of usage, just for clarity:
Range<10, 3> r(3); /*here we use it as usual, pay attention begin is
now the second argument and not the first */
Range<10> r(0); /* here we don't give a BEGIN argument, the
compiler will use the default one */

Related

Create contiguous_iterator for custom class

Summary
I have a custom array class:
template<typename T, int SIZE>
class Array {
private:
T mArray[SIZE];
};
To enable support for std algorithms, with ranges, I want to create an iterator for this class. It would seem that std::contiguous_iterator would be the optimal choice since I can guarantee contiguous memory layout for the data. Following the iterator tutorial I should create a class inside this class. However, I should somehow be (quoted) "For example, instead of the std::forward_iterator_tag tag you would mark your iterator with the std::forward_iterator concept.".
I have a hard time figuring out what the syntax would look like for this, and I have been unable to find a post on the web showcasing this.
Question
How do I complete the following code snippet to implement std::contiguous_iterator for my Array<T,S> class?:
import <iterator>;
template<typename T, int SIZE>
class Array {
public:
const T& operator[](int i) { return mArray[i]; }
T& operator[](int i) { return mArray[i]; }
private:
T mArray[SIZE];
public:
struct Iterator {
Iterator(T* ptr) : mPtr(ptr) {}
private:
T* mPtr;
};
Iterator begin() { return Iterator(&mArray[0]); }
Iterator end() { return Iterator(&mArray[SIZE]); }
};
NOTE: There is a lot of operator overloads. An answer is not required to provide all of them. I just need an example syntax for where to place the concept, then I can probably figure out the rest.
As far as I could tell you need typedefs on the iterator class, so simply using a pointer was not sufficient. Here is an example:
#include <iterator>
#include <algorithm>
template<typename T, int SIZE>
class Array {
public:
const T& operator[](int i) const { return mArray[i]; }
T& operator[](int i) { return mArray[i]; }
private:
T mArray[SIZE];
public:
struct iterator
{
using difference_type=std::ptrdiff_t;
using value_type=std::remove_cv_t<T>;
using pointer=T*;
using reference=T&;
using iterator_category=std::random_access_iterator_tag;
using iterator_concept=std::contiguous_iterator_tag;
using self_type=iterator;
iterator(T *x) : ptr(x) {}
T operator*() { return *ptr; }
T operator->() { return ptr; }
difference_type operator-(const iterator& rhs) { return ptr-rhs.ptr; }
iterator& operator ++() { ++ptr; return *this;}
bool operator !=(const iterator& rhs) { return ptr != rhs.ptr; }
private:
T * ptr;
};
iterator begin() { return &mArray[0]; }
iterator end() { return &mArray[SIZE]; }
};
int foo(Array<int, 7>& a)
{
int sum;
for (auto x : a)
{
sum+=x;
}
return sum;
}
int goo(Array<int, 7>& a, int x)
{
auto ret=std::find(a.begin(), a.end(), x);
if (ret!=a.end()) return *ret;
return 0;
}
Note that you would likely need const_iterator and reverse_iterators for const and non-const ...
Credits
Thanks to #glenn-teitelbaum for pointing me in the right direction. I think I managed to figure out how to do this. It took a long time, so this will hopefully save someone else that trouble.
[Answering my own question]
The iterator should comply with the std::contiguous_iterator concept, so I looked at cppreference for the necessary parts. The concept is defined like this:
template<class I>
concept contiguous_iterator =
std::random_access_iterator<I> &&
std::derived_from</*ITER_CONCEPT*/<I>, std::contiguous_iterator_tag> &&
std::is_lvalue_reference_v<std::iter_reference_t<I>> &&
std::same_as<
std::iter_value_t<I>, std::remove_cvref_t<std::iter_reference_t<I>>
> &&
requires(const I& i) {
{ std::to_address(i) } ->
std::same_as<std::add_pointer_t<std::iter_reference_t<I>>>;
};
So in order to implement this concept, I must first also implement std::random_access_iterator, std::is_derived_from<[...]>, std::is_lvalue_reference_v<[...]>, and so on. This is a recursive process, especially since std::random_access_iterator builds on top of 4 other iterator types. Since this is a C++20 question, I aim to use C++20 features as much as possible (since it greatly simplifies the implementation). This is the complete iterator implementation:
template<typename T, int SIZE>
class Array
{
public:
class Iterator
{
public:
using iterator_category = std::contiguous_iterator_tag;
using iterator_concept = std::contiguous_iterator_tag;
//using difference_type = std::ptrdiff_t; // Likely the same
using difference_type = typename std::iterator<
std::contiguous_iterator_tag, T>::difference_type;
//using value_type = T;
using value_type = std::remove_cv_t<T>; // Using `T` seems sufficient
using pointer = T*;
using reference = T&;
// constructor for Array<T,S>::begin() and Array<T,S>::end()
Iterator(pointer ptr) : mPtr(ptr) {}
// std::weakly_incrementable<I>
Iterator& operator++() { ++mPtr; return *this; }
Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
Iterator() : mPtr(nullptr/*&mArray[0]*/) {} // TODO: Unsure which is correct!
// std::input_or_output_iterator<I>
reference operator*() { return *mPtr; }
// std::indirectly_readable<I>
friend reference operator*(const Iterator& it) { return *(it.mPtr); }
// std::input_iterator<I>
// No actions were needed here!
// std::forward_iterator<I>
// In C++20, 'operator==' implies 'operator!='
bool operator==(const Iterator& it) const { return mPtr == it.mPtr; }
// std::bidirectional_iterator<I>
Iterator& operator--() { --mPtr; return *this; }
Iterator operator--(int) { Iterator tmp = *this; --(*this); return tmp; }
// std::random_access_iterator<I>
// std::totally_ordered<I>
std::weak_ordering operator<=>(const Iterator& it) const {
return std::compare_three_way{}(mPtr, it.mPtr);
// alternatively: `return mPtr <=> it.mPtr;`
}
// std::sized_sentinel_for<I, I>
difference_type operator-(const Iterator& it) const { return mPtr - it.mPtr; }
// std::iter_difference<I> operators
Iterator& operator+=(difference_type diff) { mPtr += diff; return *this; }
Iterator& operator-=(difference_type diff) { mPtr -= diff; return *this; }
Iterator operator+(difference_type diff) const { return Iterator(mPtr + diff); }
Iterator operator-(difference_type diff) const { return Iterator(mPtr - diff); }
friend Iterator operator+(difference_type diff, const Iterator& it) {
return it + diff;
}
friend Iterator operator-(difference_type diff, const Iterator& it) {
return it - diff;
}
reference operator[](difference_type diff) const { return mPtr[diff]; }
// std::contiguous_iterator<I>
pointer operator->() const { return mPtr; }
using element_type = T;
private:
T* mPtr;
};
// === STATIC ASSERTS ===
// - to verify correct Iterator implementation!
static_assert(std::weakly_incrementable<Iterator>);
static_assert(std::input_or_output_iterator<Iterator>);
static_assert(std::indirectly_readable<Iterator>);
static_assert(std::input_iterator<Iterator>);
static_assert(std::incrementable<Iterator>);
static_assert(std::forward_iterator<Iterator>);
static_assert(std::bidirectional_iterator<Iterator>);
static_assert(std::totally_ordered<Iterator>);
static_assert(std::sized_sentinel_for<Iterator, Iterator>);
static_assert(std::random_access_iterator<Iterator>);
static_assert(std::is_lvalue_reference_v<std::iter_reference_t<Iterator>>);
static_assert(std::same_as<std::iter_value_t<Iterator>,
std::remove_cvref_t<std::iter_reference_t<Iterator>>>);
static_assert(std::contiguous_iterator<Iterator>);
const T& operator[](int i) const {
if (i < 0 || i >= SIZE) {
throw std::runtime_error("Array index out of bounds");
}
return mArray[i];
}
T& operator[](int i) {
if (i < 0 || i >= SIZE) {
throw std::runtime_error("Array index out of bounds");
}
return mArray[i];
}
Iterator begin() { return Iterator(&mArray[0]); }
Iterator end() { return Iterator(&mArray[SIZE]); }
private:
T mArray[SIZE];
};
// Check that the Array class can be used as a contiguous_range.
static_assert(std::ranges::contiguous_range<Array<int, 10>>);
NOTE: using element_type = T; was necessary because of a bug in the specification, which might be fixed. I found information about that here. Adding this fixed issue with std::to_address<Iterator> not being able to compile, and was the last missing piece in going from std::random_access_iterator to std::contiguous_iterator.
Testing
I did not perform a complete testing suite with all algorithms, but I chose a few which depend on ranges and std::random_access_iterator. It all runs smoothly. I also depend on building standard library headers as module units, because I want to showcase how C++20 features work together.
import <stdexcept>;
import <iostream>;
import <iterator>;
import <algorithm>;
import <random>;
#include <memory> // fails to build header unit!
template<typename T, int SIZE>
class Array
{
[...]
};
int main()
{
Array<int, 10> arr;
for (int i = 0; i < 10; i++) arr[i] = i;
// I need to call std::ragnes::shuffle since that depends on
// std::random_access_iterator, so that is a minimum.
// https://en.cppreference.com/w/cpp/algorithm/ranges/shuffle
std::random_device rd;
std::mt19937 gen{rd()};
std::cout << "before random shuffle:\n";
for (auto& i : arr) std::cout << i << ' ';
std::ranges::shuffle(arr, gen);
std::cout << "\nafter random shuffle:\n";
for (auto& i : arr) std::cout << i << ' ';
std::cout << '\n';
// Also std::ranges::stable_sort is a good check (also random_access_iterator):
// https://en.cppreference.com/w/cpp/algorithm/ranges/stable_sort
std::cout << "after stable_sort:\n";
std::ranges::stable_sort(arr);
for (auto& i : arr) std::cout << i << ' ';
std::cout << '\n';
auto [min,max] = std::ranges::minmax(arr);
std::cout << "min: " << min << ", max: " << max << '\n';
return 0;
}

C++ iterate over members of struct

Say I have a struct:
struct Boundary {
int top;
int left;
int bottom;
int right;
}
and a vector
std::vector<Boundary> boundaries;
What would be the most C++ style way to access the structs to get the sum of top, left, bottom and right separately?
I could write a loop like
for (auto boundary: boundaries) {
sum_top+=boundary.top;
sum_bottom+=boundary.bottom;
...
}
This seems like a lot of repetition. Of course I could do this instead:
std::vector<std::vector<int>> boundaries;
for (auto boundary: boundaries) {
for(size_t i=0; i<boundary.size();i++) {
sums.at(i)+=boundary.at(i)
}
}
But then I'd loose all the meaningful struct member names. Is there a way so that I can write a something like the following function:
sum_top=make_sum(boundaries,"top");
Reflection does not seem to be an option in C++. I am open to use C++ up to Version 14.
std::accumulate(boundaries.begin(), boundaries.end(), 0,
[](Boundary const & a, Boundary const & b) { return a.top + b.top); });
(IIRC the Boundary const &'s can be auto'd in C++17)
This doesn't make it generic for the particular element, which - indeed, due to the lack of reflection - isn't easy to generalize.
There are a few ways to ease your pain, though;
You could use a pointer-to-member, which is fine for your szenario but not very c-plusplus-y:
int Sum(vector<Boundary>const & v, int Boundary::*pMember)
{
return std::accumulate( /*...*/,
[&](Boundary const & a, Boundary const & b)
{
return a.*pMember + b.*pMember;
});
}
int topSum = Sum(boundaries, &Boundary::top);
(For pointer-to-member, see e.g. here: Pointer to class data member "::*")
You could also make this generic (any container, any member type), and you could also replace the pointer-to-member with a lambda (also allowing member functions)
You can achieve the desired effect with Boost Hana reflection:
#include <iostream>
#include <vector>
#include <boost/hana.hpp>
struct Boundary {
BOOST_HANA_DEFINE_STRUCT(Boundary,
(int, top),
(int, left),
(int, bottom),
(int, right)
);
};
template<class C, class Name>
int make_sum(C const& c, Name name) {
int sum = 0;
for(auto const& elem : c) {
auto& member = boost::hana::at_key(elem, name);
sum += member;
}
return sum;
}
int main() {
std::vector<Boundary> v{{0,0,1,1}, {1,1,2,2}};
std::cout << make_sum(v, BOOST_HANA_STRING("top")) << '\n';
std::cout << make_sum(v, BOOST_HANA_STRING("bottom")) << '\n';
}
See Introspecting user-defined types for more details.
I am probably a bit late to the party, but I wanted to add answer inspired by the one of #TobiasRibizel. Instead of adding much boilerplate code to your struct we add more boilerplate code once in the form of an iterator over (specified) members of a struct.
#include <iostream>
#include <string>
#include <map>
template<class C, typename T, T C::* ...members>
class struct_it {
public:
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
using iterator_category = std::bidirectional_iterator_tag;
constexpr struct_it (C &c) : _index{0}, _c(c)
{}
constexpr struct_it (size_t index, C &c) : _index{index}, _c(c)
{}
constexpr static struct_it make_end(C &c) {
return struct_it(sizeof...(members), c);
}
constexpr bool operator==(const struct_it& other) const {
return other._index == _index; // Does not check for other._c == _c, since that is not always possible. Maybe do &other._c == &_c?
}
constexpr bool operator!=(const struct_it& other) const {
return !(other == *this);
}
constexpr T& operator*() const {
return _c.*_members[_index];
}
constexpr T* operator->() const {
return &(_c.*_members[_index]);
}
constexpr struct_it& operator--() {
--_index;
return *this;
}
constexpr struct_it& operator--(int) {
auto copy = *this;
--_index;
return copy;
}
constexpr struct_it& operator++() {
++_index;
return *this;
}
constexpr struct_it& operator++(int) {
auto copy = *this;
++_index;
return copy;
}
private:
size_t _index;
C &_c;
std::array<T C::*, sizeof...(members)> _members = {members...}; // Make constexpr static on C++17
};
template<class C, typename T, T C::* ...members>
using cstruct_it = struct_it<const C, T, members...>;
struct boundary {
int top;
int bottom;
int left;
int right;
using iter = struct_it<boundary, int, &boundary::top, &boundary::bottom, &boundary::left, &boundary::right>;
using citer = cstruct_it<boundary, int, &boundary::top, &boundary::bottom, &boundary::left, &boundary::right>;
iter begin() {
return iter{*this};
}
iter end() {
return iter::make_end(*this);
}
citer cbegin() const {
return citer{*this};
}
citer cend() const {
return citer::make_end(*this);
}
};
int main() {
boundary b{1,2,3,4};
for(auto i: b) {
std::cout << i << ' '; // Prints 1 2 3 4
}
std::cout << '\n';
}
It works on C++14, on C++11 the constexpr functions are all const by default so they don't work, but just getting rid of the constexpr should do the trick. The nice thing is that you can choose just some members of your struct and iterate over them. If you have the same few members that you will always iterate over, you can just add a using. That is why I chose to make the pointer-to-members part of the template, even if it is actually not necessary, since I think that only the iterators over the same members should be of the same type.
One could also leave that be, replace the std::array by an std::vector and choose at runtime over which members to iterate.
Without going too much into the memory layout of C++ objects, I would propose replacing the members by 'reference-getters', which adds some boilerplate code to the struct, but except for replacing top by top() doesn't require any changes in the way you use the struct members.
struct Boundary {
std::array<int, 4> coordinates;
int& top() { return coordinates[0]; }
const int& top() const { return coordinates[0]; }
// ...
}
Boundary sum{};
for (auto b : boundaries) {
for (auto i = 0; i < 4; ++i) {
sum.coordinates[i] += b.coordinates[i];
}
}

Custom container range-based iteration

I have a custom container which I want to use in a ranged-based for loop. The container is somewhat based on a vector, like this:
template<typename T>
class IDMap
{
private:
struct Item {
uint16_t mVersion;
T mItem;
template <typename... Arguments>
Item(uint16_t version, Arguments&&... args) : mVersion(version), mItem(args...)
{
}
};
public:
typedef uint32_t ItemID;
template <typename... Arguments>
ItemID AddItem(Arguments&&... args);
void MarkAsFree(const ItemID id);
T& GetItem(const ItemID id);
T* TryGetItem(const ItemID id);
void Clear();
private:
std::vector<Item> mItems;
std::vector<uint16_t> mFreeIndices;
};
I want to iterate the mItems vector, but only return the mItem member rather than the entire Item struct. Is there any easy/elegant way to do this?
You have to provide a begin and end function, both returning a corresponding iterator, which itself implements operators ++, != and *. The begin and end functions can be free-standing or as members.
Start with implementing an iterator which has the behavior you want. You can implement it as a wrapper around a std::vector::iterator to save most of the "core" work.
The following is untested code
Basically, inside class IDMap, add:
class ItemIterator {
// based on vector iterator
std::vector<Item>::iterator i;
public:
ItemIterator(std::vector<Item>::iterator i) : i(i) {}
// incrementing
ItemIterator & operator ++() { ++i; return *this; }
ItemIterator operator ++(int) { const_iterator old(*this); ++(*this); return old; }
// comparison
bool operator!=(const ItemIterator &o) const { return i != o.i; }
// dereferencing
const T & operator*() const { return i->mItem; }
};
using iterator = ItemIterator;
using value_type = T;
ItemIterator begin() const { return ItemIterator(mItems.begin()); }
ItemIterator end() const { return ItemIterator(mItems.end() ); }
If you ever want to support multiple kinds of "special iteration" over your IDMap, like for example also over the indices, or over the "whole" Items, you should wrap everything above in another adaptor. This adaptor can then be accessed with a member method, like .items().
Brief example:
class IDMap {
// (your code)
public:
struct ItemsAdaptor {
// (insert above iterator definition + usings)
ItemsAdaptor(std::vector<Item>::iterator b,
std::vector<Item>::iterator e)
: b{b}, e{e}
{}
ItemIterator begin() const { return b; }
ItemIterator end() const { return e; }
private:
ItemIterator b, e;
};
ItemsAdaptor items() const {
return ItemsAdaptor(mItems.begin(), mItems.end());
}
};
Then, you can write:
IDMap<int> map = ...;
for (int i : map.items()) {
...
}
If you want the range-based for to work for your container, you have to provide begin and end functions that return forward iterators.
typedef std::vector<Item>::iterator iterator;
typedef std::vector<Item>::const_iterator const_iterator;
iterator begin()
{
return mItems.begin();
}
const_iterator begin() const;
{
return mItems.begin();
}
//also add end functions, and viola.
This will return the whole item struct. If you have to only return mItem, you'll have to write your own iterator adaptor and use it instead of vector's.

How to allow range-for loop on my class? [duplicate]

This question already has answers here:
How to make my custom type to work with "range-based for loops"?
(10 answers)
Closed 7 years ago.
I have a class like this:
class Foo {
private:
int a,b,c,d;
char bar;
double m,n
public:
//constructors here
};
I wanna allow range-for loop on my class, e.g.
Foo foo {/*...*/};
for(auto& f : foo) {
//f will be a specific order such as c,b,d,(int)m,(int)bar,a,(int)n
}
How can I achieve this? I was looking at iterator but don't know what are the requirements for a range-for loop. (Please don't ask me to use array or STL type)
The loop is defined to be equivalent to:
for ( auto __begin = <begin-expr>,
__end = <end-expr>;
__begin != __end;
++__begin ) {
auto& f = *__begin;
// loop body
}
where <begin-expr> is foo.begin(), or begin(foo) if there isn't a suitable member function, and likewise for <end-expr>. (This is a simplification of the specification in C++11 6.5.4, for this particular case where the range is a lvalue of class type).
So you need to define an iterator type that supports pre-increment ++it, dereference *it and comparison i1 != i2; and either
give foo public member functions begin() and end(); or
define non-member functions begin(foo) and end(foo), in the same namespace as foo so that they can be found by argument-dependent lookup.
This seems fairly un-C++-like, and rather prone to breakage. What if the iteration order is changed (accidentally or not) during some update in the future? Clients relying on a specific order will break.
All that said if you wish to support this all you have to do is implement your own iterator and provide begin/end methods (or free functions with those names) to provide access. Then the iterator takes care of remembering which attribute it's currently looking at and provides it when dereferenced.
Here is a basic framework I came up with:
#include <iterator>
struct Foo;
template<typename Type>
struct MemberPtrBase {
virtual ~MemberPtrBase() { }
virtual Type get() const = 0;
virtual MemberPtrBase & set(Type const &) = 0;
};
template<typename Class, typename RealType, typename CommonType>
struct MemberPtr : MemberPtrBase<CommonType> {
public:
MemberPtr(Class * object, RealType(Class::*member))
: m_object(object), m_ptr(member)
{ }
CommonType get() const {
return m_object->*m_ptr;
}
MemberPtr & set(CommonType const & val) {
m_object->*m_ptr = val;
return *this;
}
MemberPtr & operator=(RealType const & val) {
return set(val);
}
operator CommonType() const {
return get();
}
private:
Class * m_object;
RealType (Class::*m_ptr);
};
template<typename Class, typename... Types>
struct MemberIterator {
public:
using CommonType = typename std::common_type<Types...>::type;
public:
MemberIterator(Class & obj, std::size_t idx, Types(Class::*...member))
: m_object(obj), m_index(idx), m_members { new MemberPtr<Class, Types, CommonType>(&obj, member)... }
{ }
MemberPtrBase<CommonType> & operator*() const {
return *m_members[m_index];
}
bool operator==(MemberIterator const & it) const {
return (&m_object == &it.m_object) && (m_index == it.m_index);
}
bool operator!=(MemberIterator const & it) const {
return (&m_object != &it.m_object) || (m_index != it.m_index);
}
MemberIterator & operator++() {
++m_index;
return *this;
}
private:
Class & m_object;
std::size_t m_index;
MemberPtrBase<CommonType> * m_members[sizeof...(Types)];
};
struct Foo {
public:
using iterator = MemberIterator<Foo, int, int, int, int>;
public:
Foo(int a, int b, int c, int d)
: m_a(a), m_b(b), m_c(c), m_d(d)
{ }
iterator begin() {
return iterator(*this, 0, &Foo::m_b, &Foo::m_d, &Foo::m_c, &Foo::m_a);
}
iterator end() {
return iterator(*this, 4, &Foo::m_b, &Foo::m_d, &Foo::m_c, &Foo::m_a);
}
private:
int m_a, m_b, m_c, m_d;
};
If you have a basic understanding of variadic templates, I think the code is self-explanatory.
Usage is simple:
#include <iostream>
int main(int argc, char ** argv) {
Foo foo { 1, 2, 3, 4 };
for(auto & mem : foo) {
std::cout << mem.get() << std::endl;
mem.set(3);
}
for(auto & mem : foo) {
std::cout << mem.get() << std::endl;
}
}
A POC can be found on ideone

Is there a range class in C++11 for use with range based for loops?

I found myself writing this just a bit ago:
template <long int T_begin, long int T_end>
class range_class {
public:
class iterator {
friend class range_class;
public:
long int operator *() const { return i_; }
const iterator &operator ++() { ++i_; return *this; }
iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }
bool operator ==(const iterator &other) const { return i_ == other.i_; }
bool operator !=(const iterator &other) const { return i_ != other.i_; }
protected:
iterator(long int start) : i_ (start) { }
private:
unsigned long i_;
};
iterator begin() const { return iterator(T_begin); }
iterator end() const { return iterator(T_end); }
};
template <long int T_begin, long int T_end>
const range_class<T_begin, T_end>
range()
{
return range_class<T_begin, T_end>();
}
And this allows me to write things like this:
for (auto i: range<0, 10>()) {
// stuff with i
}
Now, I know what I wrote is maybe not the best code. And maybe there's a way to make it more flexible and useful. But it seems to me like something like this should've been made part of the standard.
So is it? Was some sort of new library added for iterators over a range of integers, or maybe a generic range of computed scalar values?
The C++ standard library does not have one, but Boost.Range has boost::counting_range, which certainly qualifies. You could also use boost::irange, which is a bit more focused in scope.
C++20's range library will allow you to do this via view::iota(start, end).
As far as I know, there is no such class in C++11.
Anyway, I tried to improve your implementation. I made it non-template, as I don't see any advantage in making it template. On the contrary, it has one major disadvantage : that you cannot create the range at runtime, as you need to know the template arguments at compile time itself.
//your version
auto x = range<m,n>(); //m and n must be known at compile time
//my version
auto x = range(m,n); //m and n may be known at runtime as well!
Here is the code:
class range {
public:
class iterator {
friend class range;
public:
long int operator *() const { return i_; }
const iterator &operator ++() { ++i_; return *this; }
iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }
bool operator ==(const iterator &other) const { return i_ == other.i_; }
bool operator !=(const iterator &other) const { return i_ != other.i_; }
protected:
iterator(long int start) : i_ (start) { }
private:
unsigned long i_;
};
iterator begin() const { return begin_; }
iterator end() const { return end_; }
range(long int begin, long int end) : begin_(begin), end_(end) {}
private:
iterator begin_;
iterator end_;
};
Test code:
int main() {
int m, n;
std::istringstream in("10 20");
if ( in >> m >> n ) //using in, because std::cin cannot be used at coliru.
{
if ( m > n ) std::swap(m,n);
for (auto i : range(m,n))
{
std::cout << i << " ";
}
}
else
std::cout <<"invalid input";
}
Output:
10 11 12 13 14 15 16 17 18 19
Onine demo.
I wrote a library called range for exactly the same purpose except it is a run-time range, and the idea in my case came from Python. I considered a compile-time version, but in my humble opinion there is no real advantage to gain out the compile-time version. You can find the library on bitbucket, and it is under Boost License: Range. It is a one-header library, compatible with C++03 and works like charm with range-based for loops in C++11 :)
Features:
A true random access container with all the bells and whistles!
Ranges can be compared lexicographically.
Two functions exist(returns
bool), and find(returns iterator) to check the existence of a number.
The library is unit-tested using CATCH.
Examples of basic
usage, working with standard containers, working with standard
algorithms and working with range based for loops.
Here is a one-minute introduction. Finally, I welcome any suggestion about this tiny library.
I found that boost::irange was much slower than the canonical integer loop. So I settled on the following much simpler solution using a preprocessor macro:
#define RANGE(a, b) unsigned a=0; a<b; a++
Then you can loop like this:
for(RANGE(i, n)) {
// code here
}
This range automatically starts from zero. It could be easily extended to start from a given number.
Here is a simpler form which is working nicely for me. Are there any risks in my approach?
r_iterator is a type which behaves, as much as possible, like a long int. Therefore many operators such as == and ++, simply pass through to the long int. I 'expose' the underlying long int via the operator long int and operator long int & conversions.
#include <iostream>
using namespace std;
struct r_iterator {
long int value;
r_iterator(long int _v) : value(_v) {}
operator long int () const { return value; }
operator long int& () { return value; }
long int operator* () const { return value; }
};
template <long int _begin, long int _end>
struct range {
static r_iterator begin() {return _begin;}
static r_iterator end () {return _end;}
};
int main() {
for(auto i: range<0,10>()) { cout << i << endl; }
return 0;
}
(Edit: - we can make the methods of range static instead of const.)
This might be a little late but I just saw this question and I've been using this class for a while now :
#include <iostream>
#include <utility>
#include <stdexcept>
template<typename T, bool reverse = false> struct Range final {
struct Iterator final{
T value;
Iterator(const T & v) : value(v) {}
const Iterator & operator++() { reverse ? --value : ++value; return *this; }
bool operator!=(const Iterator & o) { return o.value != value; }
T operator*() const { return value; }
};
T begin_, end_;
Range(const T & b, const T & e) : begin_(b), end_(e) {
if(b > e) throw std::out_of_range("begin > end");
}
Iterator begin() const { return reverse ? end_ -1 : begin_; }
Iterator end() const { return reverse ? begin_ - 1: end_; }
Range() = delete;
Range(const Range &) = delete;
};
using UIntRange = Range<unsigned, false>;
using RUIntRange = Range<unsigned, true>;
Usage :
int main() {
std::cout << "Reverse : ";
for(auto i : RUIntRange(0, 10)) std::cout << i << ' ';
std::cout << std::endl << "Normal : ";
for(auto i : UIntRange(0u, 10u)) std::cout << i << ' ';
std::cout << std::endl;
}
have you tried using
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function f);
Most of the time fits the bill.
E.g.
template<class T> void printInt(T i) {cout<<i<<endl;}
void test()
{
int arr[] = {1,5,7};
vector v(arr,arr+3);
for_each(v.begin(),v.end(),printInt);
}
Note that printInt can OFC be replaced with a lambda in C++0x.
Also one more small variation of this usage could be (strictly for random_iterator)
for_each(v.begin()+5,v.begin()+10,printInt);
For Fwd only iterator
for_each(advance(v.begin(),5),advance(v.begin(),10),printInt);
You can easily generate an increasing sequence in C++11 using std::iota():
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
template<typename T>
std::vector<T> range(T start, T end)
{
std::vector<T> r(end+1-start, T(0));
std::iota(r.begin(), r.end(), T(start));//increasing sequence
return r;
}
int main(int argc, const char * argv[])
{
for(auto i:range<int>(-3,5))
std::cout<<i<<std::endl;
return 0;
}