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
|
// This example illustrates how we can reduce the usage of templates (or the amount of different instantiations) via
// type erasure. Having only one function generated for `algorithm()` is the only benefit of using `semialphabet_any`
// here. Of course this only makes sense for your application if the part of the program that is agnostic of the
// character representation (your equivalent of `algorithm()`) is substantially larger than the specific parts – and
// if compile-time and/or size of the exectuble are a concern.
#include <iostream>
#include <seqan3/alphabet/aminoacid/all.hpp>
#include <seqan3/alphabet/composite/semialphabet_any.hpp>
#include <seqan3/core/debug_stream.hpp>
#include <seqan3/utility/range/to.hpp>
using namespace seqan3::literals;
// Print is a template and gets instantiated two times because the behaviour is different for both types
template <typename rng_t>
void print(rng_t && r)
{
seqan3::debug_stream << r << '\n';
}
// Algorithm is not a template, only one instance is generated by the compiler
// Type information is encoded via a run-time parameter
void algorithm(std::vector<seqan3::semialphabet_any<10>> & r, bool is_murphy)
{
// Algorithm example that replaces rank 0 with rank 1
for (auto & v : r)
if (seqan3::to_rank(v) == 0)
seqan3::assign_rank_to(1, v);
// Here we reify the type for printing
if (is_murphy)
print(r
| std::views::transform(
[](auto const & in)
{
return static_cast<seqan3::aa10murphy>(in);
}));
else
print(r
| std::views::transform(
[](auto const & in)
{
return static_cast<seqan3::aa10li>(in);
}));
}
// Two instances of algo_pre exist
// They type erase the different arguments to the same type and encode the type information as a run-time parameter
void algo_pre(seqan3::aa10li_vector const & v)
{
std::vector<seqan3::semialphabet_any<10>> tmp = v
| std::views::transform(
[](auto const & in)
{
return static_cast<seqan3::semialphabet_any<10>>(in);
})
| seqan3::ranges::to<std::vector>();
algorithm(tmp, false);
}
void algo_pre(seqan3::aa10murphy_vector const & v)
{
std::vector<seqan3::semialphabet_any<10>> tmp = v
| std::views::transform(
[](auto const & in)
{
return static_cast<seqan3::semialphabet_any<10>>(in);
})
| seqan3::ranges::to<std::vector>();
algorithm(tmp, true);
}
int main()
{
seqan3::aa10li_vector v1{"AVRSTXOUB"_aa10li};
algo_pre(v1); // BIKBBBKCB
seqan3::aa10murphy_vector v2{"AVRSTXOUB"_aa10murphy};
algo_pre(v2); // BIKSSSKCB
}
|