template<class...Fs>
void do_in_order(Fs&&...fs) {
int _[]={0, (std::forward<Fs>(fs)(), void(), 0)...};
(void)_;
}
छुपाता है सिंटैक्स को बाएं से दाएं क्रम में फ़ंक्शन ऑब्जेक्ट्स के पैक को निष्पादित करने के लिए आवश्यक है।
फिर
:
struct Bar {
template <class... Ts>
void foo() {
do_in_order([&]{
using T = Ts;
// code
}...);
}
};
और एक अनुरूप संकलक में, हम // code
T
बाएं से दाएं प्रत्येक प्रकार के होने के साथ चलेंगे।
ध्यान दें कि सी ++ 11 कंपाइलर होने का दावा करने वाले कुछ कंपाइलर्स उपरोक्त संकलित करने में विफल हो सकते हैं।
इस तकनीक का लाभ यह है कि यह एक स्पष्ट नाम के साथ एक समारोह के भीतर "विस्तार और मूल्यांकन टेम्पलेट्स" कोड को छुपाता है। आप एक बार do_in_order
लिखते हैं, और यह आमतौर पर उस सरणी-विस्तार चाल के लगभग हर उपयोग के लिए पर्याप्त होता है।
"अधिक सरल" पुनरावर्ती समाधानों के बजाय इस तरह के गूढ़ वाक्यविन्यास का उपयोग करने के दो महत्वपूर्ण कारण हैं।
सबसे पहले, यह अनुकूलक के लिए चीजों को आसान बनाता है। कभी-कभी ऑप्टिमाइज़र रिकर्सिव कॉल के ढेर के बाद छोड़ देते हैं।
दूसरा, परंपरागत रिकर्सिव कार्यों के लिए फ़ंक्शन हस्ताक्षर की लंबाई के नामों की योग ओ (एन^2) में बढ़ती है। यदि आप सहायक प्रकार का उपयोग करते हैं, तो नामों की कुल लंबाई भी ओ (एन^2) है। जब तक आप सावधान न हों, यह संकलन समय, लिंक समय और बाइनरी आकार के ब्लोट का कारण बन सकता है।
सी ++ 1z में कुछ "गुना" वाक्यविन्यास के लिए योजनाएं हैं जो उपर्युक्त कम गूढ़ के गूढ़ भागों को बना सकती हैं।
हुह? 'foo' कोई तर्क नहीं लेता है। – MadScientist
नकारात्मक पक्ष के रूप में, इसे एन प्रकारों के लिए एन रिकर्सिव चरणों की आवश्यकता होती है, और उन प्रकारों और कार्यों को तत्काल करता है जिनके नाम की लंबाई ओ (एन^2) के बराबर होती है। एन के साथ उपरोक्त बड़े कारणों से धीमी संकलन धीमी होती है, और यदि उन नामों को संकलक द्वारा नहीं हटाया जाता है तो बाइनरी ब्लोट का कारण बन सकता है। – Yakk