可以做到这一点,但需要花一些步骤才能干净地做。首先,写一个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。