File: solution_iterator.cpp

package info (click to toggle)
seqan3 3.0.2%2Bds-9
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 16,052 kB
  • sloc: cpp: 144,641; makefile: 1,288; ansic: 294; sh: 228; xml: 217; javascript: 50; python: 27; php: 25
file content (95 lines) | stat: -rw-r--r-- 3,568 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//![start]
#include <iostream>
#include <vector>
#include <seqan3/alphabet/nucleotide/all.hpp>
#include <seqan3/std/ranges>

using seqan3::operator""_dna5;

template <std::ranges::forward_range urng_t> // the underlying range type
struct my_iterator : std::ranges::iterator_t<urng_t>
{
//![start]
    //![static_assert]
    static_assert(seqan3::nucleotide_alphabet<std::ranges::range_reference_t<urng_t>>,
                  "You can only iterate over ranges of nucleotides!");
    //![static_assert]

    //![solution1a]
    using base_t = std::ranges::iterator_t<urng_t>;

    // these member types are just exposed from the base type
    using value_type            = typename std::iterator_traits<base_t>::value_type;
    using pointer               = typename std::iterator_traits<base_t>::pointer;
    //![solution1a]
    //![reference]
    // If the value_type is seqan3::dna5, the reference type of the vector is
    // seqan3::dna5 & and operator* returns this so you can change the values
    // in the vector through it's iterator.
    // This won't work anymore, because now we are creating new values on access
    // so we now need to change this type to reflect that:
    using reference             = value_type;
    //![reference]

    //![solution1b]
    // this member type is explicitly set to forward_iterator_tag because we are not
    // implementing the remaining requirements
    using iterator_category     = std::forward_iterator_tag;

    // the following operators need to be explicitly defined, because the inherited
    // version has wrong return types (base_t instead of my_iterator)
    my_iterator & operator++()
    {
        base_t::operator++();       // call the implementation of the base type
        return *this;
    }

    my_iterator operator++(int)
    {
        my_iterator cpy{*this};
        ++(*this);
        return cpy;
    }

    // we do not need to define constructors, because {}-initialising this with one argument
    // calls the base-class's constructor which is what we want
    // NOTE: depending on your view/iterator, you might need/want to define your own

    // we do not need to define comparison operators, because there are comparison operators
    // for the base class and our type is implicitly convertible to the base type
    // NOTE: in our case comparing the converted-to-base iterator with end behaves as desired,
    // but it strongly depends on your view/iterator whether the same holds
    //![solution1b]

    //![dereference]
    // The operator* facilitates the access to the element.
    // This implementation calls the base class's implementation but passes the return value
    // through the seqan3::complement() function before returning it.
    reference operator*() const
    {
        return seqan3::complement(base_t::operator*());
    }
    //![dereference]

//![end]
};

// verify that your type models the concept
static_assert(std::forward_iterator<my_iterator<std::vector<seqan3::dna5>>>);

int main()
{
    std::vector<seqan3::dna5> vec{"GATTACA"_dna5};

    // instantiate the template over the underlying vector's iterator and sentinel
    // (for all standard containers the sentinel type is the same as the iterator type)
    using my_it_concrete = my_iterator<std::vector<seqan3::dna5>>;

    // create an iterator that is constructed with vec.begin() as the underlying iterator
    my_it_concrete it{vec.begin()};

    // iterate over vec, but with your custom iterator
    while (it != vec.end())
        std::cout << seqan3::to_char(*it++) << ' ';
}
//![end]