可以做到这一点,但需要花一些步骤才能干净地做。首先,写一个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) {}
// 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 );
}
(未经测试,但设计应该可以使用)。
然后,在您的.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
。