Điều này có thể được thực hiện, nhưng cần một vài bước để thực hiện sạch sẽ. Đầu tiên, hãy viết một template class
đại diện cho một loạt các giá trị liền nhau. Sau đó, chuyển tiếp một template
phiên bản biết mức độ lớn array
đến Impl
phiên bản có phạm vi tiếp giáp này.
Cuối cùng, thực hiện contig_range
phiên bản. Lưu ý rằng điều đó for( int& x: range )
hoạt động contig_range
vì tôi đã triển khai begin()
và end()
và con trỏ là các trình vòng lặp.
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 );
}
(không được thử nghiệm, nhưng thiết kế sẽ hoạt động).
Sau đó, trong .cpp
tệp của bạn :
void mulArrayImpl(contig_range<int> rng, const int multiplier) {
for(auto& e : rng) {
e *= multiplier;
}
}
Điều này có nhược điểm là mã lặp qua nội dung của mảng không biết (tại thời điểm biên dịch) mảng lớn như thế nào, điều này có thể tốn chi phí tối ưu hóa. Nó có lợi thế là việc triển khai không cần phải có trong tiêu đề.
Hãy cẩn thận về việc xây dựng một cách rõ ràng a contig_range
, vì nếu bạn chuyển nó a, set
nó sẽ cho rằng set
dữ liệu là liền kề, điều này là sai và thực hiện hành vi không xác định ở khắp nơi. Hai vùng std
chứa duy nhất mà điều này được đảm bảo hoạt động là vector
và array
(và mảng kiểu C, khi nó xảy ra!). deque
mặc dù là truy cập ngẫu nhiên không liền kề (nguy hiểm là nó tiếp giáp theo từng phần nhỏ!), list
thậm chí không gần nhau và các vùng chứa kết hợp (có thứ tự và không có thứ tự) cũng không liền nhau.
Vì vậy, các nhà xây dựng ba tôi thực hiện ở đâu std::array
, std::vector
và C-style mảng, mà về cơ bản bao gồm các căn cứ.
Việc triển khai []
cũng dễ dàng và giữa for()
và []
đó là hầu hết những gì bạn muốn array
, phải không?
std::vector
.