यह किया जा सकता है, लेकिन इसे साफ करने के लिए कुछ कदम उठाए जाते हैं। सबसे पहले, एक लिखें जो template class
सन्निहित मूल्यों की एक श्रृंखला का प्रतिनिधित्व करता है। फिर एक template
संस्करण को आगे बढ़ाएं जो जानता array
है Impl
कि इस सन्निहित सीमा को लेने वाले संस्करण के लिए कितना बड़ा है ।
अंत में, contig_range
संस्करण को लागू करें । ध्यान दें कि for( int& x: range )
के लिए काम करता contig_range
है, क्योंकि मैं लागू किया begin()
और end()
और संकेत iterators हैं।
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;
}
}
इसका नकारात्मक पक्ष यह है कि सरणी की सामग्री पर लूप कोड कोड (संकलन समय पर) नहीं जानता कि सरणी कितना बड़ा है, जो कि अनुकूलन को खर्च कर सकता है। इसका यह फायदा है कि कार्यान्वयन हेडर में नहीं होता है।
स्पष्ट रूप से निर्माण के बारे में सावधान रहें contig_range
, जैसे कि आप इसे पास करते हैं, set
यह मान लेगा कि set
डेटा सन्निहित है, जो गलत है, और सभी जगह अपरिभाषित व्यवहार करते हैं। केवल दो std
कंटेनरों कि यह काम करने की गारंटी है vector
और array
(और सी-स्टाइल सरणियों, जैसा कि ऐसा होता है!)। deque
यादृच्छिक अभिगम होने के बावजूद यह खतरनाक नहीं है (खतरनाक रूप से, यह छोटे टुकड़ों में सन्निहित है!), list
करीब भी नहीं है, और साहचर्य (आदेशित और अव्यवस्थित) कंटेनर समान रूप से गैर-संक्रामक हैं।
इसलिए जिन तीन कंस्ट्रक्टरों को मैंने लागू किया है std::array
, वे हैं, std::vector
और सी-स्टाइल सरणियाँ, जो मूल रूप से आधारों को कवर करती हैं।
लागू []
करना आसान है, और बीच में है for()
और []
जो आप के लिए सबसे ज्यादा चाहते हैं array
, है ना?
std::vector
।