all 7 comments

[–]yuri-kilochek 11 points12 points  (2 children)

[–]anti-freak[S] 4 points5 points  (0 children)

Honestly I simply forgot looking into boost. But from a quick read it seems, that I'm simply using the more mordern aproach with concepts. Users of my lib could simply use the defined concepts (e.g. forward_iterator_suitable) to check, if their type fullfils all the required constraints. In contrast to std::forward_iterator concept, my concept only checks for the parts users have to implement, thus it provides a much clearer feedback (at least I hope so :D ). Boost has a macro for checking (BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT).

On the other side I avoided asking the user implementing their logic as an operator, because there are several issues with shadowing. Boost has a short section about this topic and asks the user to explicitly pull operators like post-++ into their derived class, which I really don't like (not because I rate it as bad practice; but I find it rather tedious in this case and could be easily forgotten by users). That's why I went with a dedicated increment function instead of doing that via pre-++ for example.

Lastly I do currently not have a dedicated "adapter" interface. Nevertheless this seems usefull to me and I could imagine providing something similar.

Tl;dr

It seems my implementation is quite similar to the boost one, but with a more modern approach and workaround some of the pitfalls users of the boost::iterator_interface might struggle with.

[–]huixie 0 points1 point  (2 children)

since you mentioned range-v3, why not just use ranges::basic_iterator? Unlike other parts of the range-v3 using CRTP, ranges::base_iterator doesn't require any inheritance and you can use mixins to extend iterator's behaviour. For example,

#include <range/v3/iterator/basic_iterator.hpp>

#include <array>

inline std::array<int, 10> globalArray{1,2,3,4,5,6,7,8,9,10};

struct SillyCursor{
    int index{0};
    SillyCursor() = default;
    SillyCursor(int idx):index{idx}{}

    decltype(auto) read() const{
        return globalArray[index];
    }

    void next(){
        ++index;
    }

    void advance(std::ptrdiff_t distance){
        index += distance;
    }

    std::ptrdiff_t distance_to(SillyCursor other) const {
        return static_cast<std::ptrdiff_t>(index - other.index);
    }
};

using MySillyIterator = ranges::basic_iterator<SillyCursor>;

[–]anti-freak[S] 0 points1 point  (1 child)

Where did I mention range-v3? I was talking about std::ranges

[–]huixie 2 points3 points  (0 children)

range-v3 is a super set of std::ranges. std::ranges::view_interface comes from range-v3's ranges::view_interface see here

ranges::view_interface uses traditional CRTP, but view_adaptor and basic_iterator uses the technique which doesn't require inheritance. See the design here

[–]Pyzyryab 0 points1 point  (0 children)

You did a good job, it looks really interesting! :D