Мне кажется, это идеально подходит для пользовательского итератора. Таким образом, ваша основная программа может быть простой:
std::vector<std::string> v;
v.reserve(kmerIterator<4>::end() - kmerIterator<4>::begin());
std::copy(kmerIterator<4>::begin(), kmerIterator<4>::end(),
std::back_inserter(v));
Но, поскольку мы реализовали концепцию kmer в качестве интегратора, мы можем использовать и все другие универсальные алгоритмы. Поскольку мы реализовали итератор kmer как итератор произвольного доступа, поиск i-го kmer тривиален:
kmerIterator<4>::begin()[i]
Вот моя полная программа:
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
template<unsigned int n>
class kmerIterator :
public std::iterator<std::random_access_iterator_tag,
std::string,
unsigned int>
{
private:
typedef kmerIterator k; // 'cause I'm lazy
difference_type it;
kmerIterator(difference_type i) : it(i) {}
public:
kmerIterator() : it() {}
static k begin() {
return 0;
}
static k end() {
return difference_type(1) << n*2;
}
k& operator++() { ++it; return *this; }
k operator++(int) { return it++; }
k& operator--() { --it; return *this; }
k operator--(int) { return it--; }
k operator+(difference_type delta) { return it + delta; }
k operator-(difference_type delta) { return it - delta; }
difference_type operator-(const k& rhs) { return it - rhs.it; }
bool operator<(const k& rhs) const { return it < rhs.it; }
bool operator>(const k& rhs) const { return it > rhs.it; }
bool operator<=(const k& rhs) const { return it <= rhs.it; }
bool operator>=(const k& rhs) const { return it >= rhs.it; }
k operator+=(difference_type delta) { return it+=delta; }
k operator-=(difference_type delta) { return it-=delta; }
std::string operator[](difference_type delta) const { return *k(it+delta); }
std::string operator*() const {
std::string rz;
int i = 2*n;
do {
i -= 2;
rz += "ACGT"[(it>>i)&3];
} while(i);
return rz;
}
};
int main() {
std::copy(kmerIterator<2>::begin(),
kmerIterator<2>::end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
std::vector<std::string> v;
v.reserve(kmerIterator<4>::end() - kmerIterator<4>::begin());
std::copy(kmerIterator<4>::begin(),
kmerIterator<4>::end(),
std::back_inserter(v));
std::cout << v[42] << "\n";
std::cout << kmerIterator<4>::begin()[56] << "\n";
}