मैं इस तरह हैरान था कि किसी ने काम करने के लिए कुछ अंकगणित-जादू आधारित लूप का प्रस्ताव नहीं किया। सी। वांग के बाद से कोई नेस्टेड छोरों के साथ एक समाधान की तलाश में है , मैं एक प्रस्ताव करूँगा:
double B[10][8][5];
int index = 0;
while (index < (10 * 8 * 5))
{
const int x = index % 10,
y = (index / 10) % 10,
z = index / 100;
do_something_on_B(B[x][y][z]);
++index;
}
खैर, यह दृष्टिकोण सुरुचिपूर्ण और लचीला नहीं है, इसलिए हम सभी प्रक्रिया को एक टेम्पलेट फ़ंक्शन में पैक कर सकते हैं:
template <typename F, typename T, int X, int Y, int Z>
void iterate_all(T (&xyz)[X][Y][Z], F func)
{
const int limit = X * Y * Z;
int index = 0;
while (index < limit)
{
const int x = index % X,
y = (index / X) % Y,
z = index / (X * Y);
func(xyz[x][y][z]);
++index;
}
}
यह टेम्पलेट फ़ंक्शन नेस्टेड लूप के रूप में भी व्यक्त किया जा सकता है:
template <typename F, typename T, int X, int Y, int Z>
void iterate_all(T (&xyz)[X][Y][Z], F func)
{
for (auto &yz : xyz)
{
for (auto &z : yz)
{
for (auto &v : z)
{
func(v);
}
}
}
}
और मनमाने आकार के 3 डी सरणी और फ़ंक्शन नाम को प्रदान करने के लिए उपयोग किया जा सकता है, जिससे पैरामीटर कटौती प्रत्येक आयाम के आकार को गिनने की कड़ी मेहनत करती है:
int main()
{
int A[10][8][5] = {{{0, 1}, {2, 3}}, {{4, 5}, {6, 7}}};
int B[7][99][8] = {{{0, 1}, {2, 3}}, {{4, 5}, {6, 7}}};
iterate_all(A, do_something_on_A);
iterate_all(B, do_something_on_B);
return 0;
}
अधिक सामान्य की ओर
लेकिन एक बार फिर, इसमें लचीलेपन की कमी होती है, क्योंकि यह केवल 3D सरणियों के लिए काम करता है, लेकिन SFINAE का उपयोग करके हम एक मनमाना आयाम के सरणियों के लिए कार्य कर सकते हैं, पहले हमें एक टेम्पलेट फ़ंक्शन की आवश्यकता होती है जो रैंक 1 के सरणियों को पुन : प्रदर्शित करता है:
template<typename F, typename A>
typename std::enable_if< std::rank<A>::value == 1 >::type
iterate_all(A &xyz, F func)
{
for (auto &v : xyz)
{
func(v);
}
}
और एक अन्य जो पुनरावृत्ति कर किसी भी रैंक के सरणियों को पुनरावृत्त करता है:
template<typename F, typename A>
typename std::enable_if< std::rank<A>::value != 1 >::type
iterate_all(A &xyz, F func)
{
for (auto &v : xyz)
{
iterate_all(v, func);
}
}
यह हमें एक मनमाना-आयाम मनमाने आकार के सरणी के सभी आयामों में सभी तत्वों को पुनरावृत्त करने की अनुमति देता है।
के साथ काम करना std::vector
कई नेस्टेड वेक्टर के लिए, समाधान मनमाने ढंग से आयामों के मनमाने आकार के सरणी में से एक को पुन: बनाता है, लेकिन SFINAE के बिना: सबसे पहले हमें एक टेम्पलेट फ़ंक्शन की आवश्यकता होगी जो std::vector
s को पुन: बनाता है और वांछित फ़ंक्शन को कॉल करता है:
template <typename F, typename T, template<typename, typename> class V>
void iterate_all(V<T, std::allocator<T>> &xyz, F func)
{
for (auto &v : xyz)
{
func(v);
}
}
और एक अन्य टेम्पलेट फ़ंक्शन जो वैक्टर के किसी भी प्रकार के वेक्टर को पुन: प्रसारित करता है और खुद को कॉल करता है:
template <typename F, typename T, template<typename, typename> class V>
void iterate_all(V<V<T, std::allocator<T>>, std::allocator<V<T, std::allocator<T>>>> &xyz, F func)
{
for (auto &v : xyz)
{
iterate_all(v, func);
}
}
नेस्टिंग स्तर के बावजूद, iterate_all
वेक्टर-ऑफ-वैक्टर संस्करण को कॉल करेगा , जब तक कि वेक्टर-ऑफ-वैल्यू संस्करण एक बेहतर मैच नहीं होगा, इस प्रकार पुनरावृत्ति को समाप्त करेगा।
int main()
{
using V0 = std::vector< std::vector< std::vector<int> > >;
using V1 = std::vector< std::vector< std::vector< std::vector< std::vector<int> > > > >;
V0 A0 = {{{0, 1}, {2, 3}}, {{4, 5}, {6, 7}}};
V1 A1 = {{{{{9, 8}, {7, 6}}, {{5, 4}, {3, 2}}}}};
iterate_all(A0, do_something_on_A);
iterate_all(A1, do_something_on_A);
return 0;
}
मुझे लगता है कि फ़ंक्शन बॉडी बहुत सरल और सीधे-आगे है ... मुझे आश्चर्य है कि यदि कंपाइलर इस लूप को अनियंत्रित कर सकता है (मुझे लगभग यकीन है कि अधिकांश कंपाइलर पहले उदाहरण को अनियंत्रित कर सकते हैं)।
देखें लाइव डेमो यहाँ ।
आशा करता हूँ की ये काम करेगा।