Это можно сделать, но чтобы все было чисто, нужно выполнить несколько шагов. Во-первых, напишите a template class
, представляющий диапазон смежных значений. Затем перенаправьте template
версию, которая знает, насколько велика array
эта Impl
версия, в версию, которая занимает этот непрерывный диапазон.
Наконец, реализуйте contig_range
версию. Обратите внимание , что for( int& x: range )
работает contig_range
, потому что я реализовал begin()
и end()
и указатели итераторы.
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 );
}
(не проверял, но дизайн должен работать).
Затем в вашем .cpp
файле:
void mulArrayImpl(contig_range<int> rng, const int multiplier) {
for(auto& e : rng) {
e *= multiplier;
}
}
У этого есть обратная сторона: код, который перебирает содержимое массива, не знает (во время компиляции), насколько велик массив, что может привести к оптимизации затрат. Его преимущество в том, что реализация не обязательно должна быть в заголовке.
Будьте осторожны при явном построении a contig_range
, так как если вы передадите его, set
он будет предполагать, что set
данные являются смежными, что является ложным, и повсюду будет вести себя неопределенно. Единственные два std
контейнера, с которыми это гарантированно будет работать, - это vector
и array
(и массивы в стиле C, как это бывает!). deque
несмотря на то, что произвольный доступ не является непрерывным (что опасно, он непрерывен небольшими порциями!), list
даже не близок, а ассоциативные (упорядоченные и неупорядоченные) контейнеры одинаково не смежны.
Итак, три конструктора, которые я реализовал std::array
, std::vector
и массивы в стиле C, которые в основном покрывают основы.
Реализация []
легко , как хорошо, так и между for()
и []
что большая часть того, что вы хотите, array
ибо, не так ли?
std::vector
.