Skip to content

Howto: Write a View

Marcel edited this page Apr 25, 2018 · 10 revisions

See Ranges for an explanation of what a view is.

All of these HowTos require:

  • GCC >= 6 or Clang >= 3.7
  • an up-to-date cone of the range-v3 git repository
  • building your apps with -std=c++14 -I/path/to/range-v3/include
  • SeqAn is not required
  • for Section 2 you can use -fconcepts and activate the respective checks

Section 1: Combining existing views

A small tutorial to write basic views as combinations/modifications of existing views. Everyone working on SeqAn3 should understand this.

HowTo write a Small View

Reverse complement view

std::string s{"ACGTTTATGT"};

// make reverse complement view
auto comp_view =                     // TODO: implement
std::cout << comp_view << '\n';      // should print [A,C,A,T,A,A,A,C,G,T]

// create infix from [1, 6)
auto comp_view_inf =                 // TODO: implement
std::cout << comp_view_inf << '\n';  // should print [C,A,T,A,A]

// transform back
auto orig_inf =                      // TODO: implement
std::cout << orig_inf << '\n';       // should print [T,T,A,T,G]

β†’Visit the HowTo←

Translation view

std::string s{"ACGTTTATGTTTACGT"};

auto v =                              // TODO: implement
std::cout << v << '\n';               // should print [T,F,M,F,T,X]

β†’View the HowTo←

Section 2 – writing a complete view from scratch

What is commonly referred to as a view, consists of multiple entities:

  1. the actual class (template) that meets the requirements of view_concept and at least also input_range_concept; by convention of the range-v3 it is called view_foo for the view called "foo"
  2. a "generator class" that overloads the () and | operators that facilitate the "piping" capabilities and return an instance of 1.; by convention of range-v3 it is called foo_fn
  3. an instance of the generator class that is the only actual user-facing part of the view; by convention of range-v3 it is called foo, in the namespace view, i.e. view::foo

If the view you are creating is just a combination of existing views, you may not need to implement 1. or even 2. We will cover an example below.

The add_constant view

We want to create a view, that works on input ranges of uint64_t and always adds the number 42, i.e. we want the following to work:

int main()
{
    std::vector<uint64_t> in{1, 4, 6, 89, 56, 45, 7};

    for (auto && i : in | view::add_constant)
        std::cout << i << ' ';
    std::cout << '\n'; // should print: 43 47 64 131 98 87 49

    // combine it with other views:
    for (auto && i : in | view::add_constant | ranges::view::take(3))
        std::cout << i << ' ';
    std::cout << '\n'; // should print: 43 47 64
}

We will first develop a full solution and then see how we can use existing ranges to simplify this.

The add_number view

Now, we will do the same as above, but this time our view will take a variable that is to be added (it could be a number other than 42, but it isn't of course):

int main()
{
    std::vector<uint64_t> in{1, 4, 6, 89, 56, 45, 7};

    for (auto && i : in | view::add_number(42))
        std::cout << i << ' ';
    std::cout << '\n'; // should print: 43 47 64 131 98 87 49

    // combine it with other views:
    for (auto && i : in | view::add_number(42) | ranges::view::take(3))
        std::cout << i << ' ';
    std::cout << '\n'; // should print: 43 47 64
}

Again, we will first develop a full solution and then see how we can use existing ranges to simplify this.

  • The full solution with an implementation of view_add_number, add_number_fn and view::add_number
  • A smaller solution with an implementation of view_add_number omitted, but not as minimal as before (we need add_number_fn).
Clone this wiki locally