Dies ist möglich, erfordert jedoch einige Schritte, um es sauber zu machen. Schreiben Sie zunächst a template class, das einen Bereich zusammenhängender Werte darstellt. Leiten Sie dann eine templateVersion, die weiß, wie groß die arrayist, an die ImplVersion weiter, die diesen zusammenhängenden Bereich einnimmt.
Implementieren Sie abschließend die contig_rangeVersion. Beachten Sie, dass dies for( int& x: range )funktioniert contig_range, da ich implementiert habe begin()und end()und Zeiger Iteratoren sind.
template<typename T>
struct contig_range {
T* _begin, _end;
contig_range( T* b, T* e ):_begin(b), _end(e) {}
T const* begin() const { return _begin; }
T const* end() const { return _end; }
T* begin() { return _begin; }
T* end() { return _end; }
contig_range( contig_range const& ) = default;
contig_range( contig_range && ) = default;
contig_range():_begin(nullptr), _end(nullptr) {}
// maybe block `operator=`? contig_range follows reference semantics
// and there really isn't a run time safe `operator=` for reference semantics on
// a range when the RHS is of unknown width...
// I guess I could make it follow pointer semantics and rebase? Dunno
// this being tricky, I am tempted to =delete operator=
template<typename T, std::size_t N>
contig_range( std::array<T, N>& arr ): _begin(&*std::begin(arr)), _end(&*std::end(arr)) {}
template<typename T, std::size_t N>
contig_range( T(&arr)[N] ): _begin(&*std::begin(arr)), _end(&*std::end(arr)) {}
template<typename T, typename A>
contig_range( std::vector<T, A>& arr ): _begin(&*std::begin(arr)), _end(&*std::end(arr)) {}
};
void mulArrayImpl( contig_range<int> arr, const int multiplier );
template<std::size_t N>
void mulArray( std::array<int, N>& arr, const int multiplier ) {
mulArrayImpl( contig_range<int>(arr), multiplier );
}
(nicht getestet, aber das Design sollte funktionieren).
Dann in Ihrer .cppDatei:
void mulArrayImpl(contig_range<int> rng, const int multiplier) {
for(auto& e : rng) {
e *= multiplier;
}
}
Dies hat den Nachteil, dass der Code, der den Inhalt des Arrays durchläuft, (zur Kompilierungszeit) nicht weiß, wie groß das Array ist, was zu einer Kostenoptimierung führen kann. Dies hat den Vorteil, dass sich die Implementierung nicht im Header befinden muss.
Seien Sie vorsichtig beim expliziten Erstellen von a contig_range, als ob Sie es übergeben würden. setEs wird davon ausgegangen, dass die setDaten zusammenhängend sind, was falsch ist, und überall undefiniertes Verhalten zeigen. Die einzigen zwei stdContainer, an denen dies garantiert funktioniert, sind vectorund array(und Arrays im C-Stil, wie es passiert!). dequeObwohl der Direktzugriff nicht zusammenhängend ist (gefährlich, er ist in kleinen Stücken zusammenhängend!), listist er nicht einmal in der Nähe und die assoziativen (geordneten und ungeordneten) Container sind gleichermaßen nicht zusammenhängend.
Also die drei Konstruktoren, die ich wo implementiert habe std::array, std::vectorund C-artige Arrays, die im Grunde die Basen abdecken.
Die Implementierung []ist ebenfalls einfach, und dazwischen for()und []das ist das meiste, wofür Sie sich wünschen array, nicht wahr?
std::vector.