Można to zrobić, ale wystarczy kilka kroków, aby zrobić to czysto. Najpierw napisz a, template classktóry reprezentuje zakres ciągłych wartości. Następnie przekaż templatewersję, która wie, jak duży arrayjest, do Implwersji, która przyjmuje ten ciągły zakres.
Na koniec zaimplementuj contig_rangewersję. Zauważ, że for( int& x: range )działa w przypadku contig_range, ponieważ zaimplementowałem begin()i, end()a wskaźniki to iteratory.
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) {}
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 );
}
(nie testowane, ale projekt powinien działać).
Następnie w swoim .cpppliku:
void mulArrayImpl(contig_range<int> rng, const int multiplier) {
for(auto& e : rng) {
e *= multiplier;
}
}
Ma to tę wadę, że kod, który zapętla zawartość tablicy, nie wie (w czasie kompilacji), jak duża jest tablica, co może kosztować optymalizację. Ma tę zaletę, że implementacja nie musi znajdować się w nagłówku.
Uważaj na jawne konstruowanie a contig_range, ponieważ jeśli przekażesz a set, przyjmie on, że setdane są ciągłe, co jest fałszywe i będzie wykonywać niezdefiniowane zachowanie w każdym miejscu. Jedyne dwa stdkontenery, na których to działa, to vectori array(oraz tablice w stylu C, jak to się dzieje!). dequepomimo tego, że dostęp losowy nie jest ciągły (niebezpiecznie, jest ciągły w małych kawałkach!), listnie jest nawet blisko, a asocjacyjne (uporządkowane i nieuporządkowane) kontenery są równie nieciągłe.
Więc trzy konstruktory, które zaimplementowałem gdzie std::array, std::vectori tablice w stylu C, które w zasadzie obejmują podstawy.
Wykonawcza []jest łatwe, jak również i między for()i []to większość tego, co chcesz, by arraydla, prawda?
std::vector.