सी ++ टेम्पलेट आम तौर पर ब्लोट के निर्माता को समेकित होते हैं, और शिम विचार बिल्कुल वैसा ही होता है: टेम्पलेट को नियमित फ़ंक्शन पर केवल एक पतला आवरण बनाते हैं। यह ब्लोट पर कटौती करने का एक बहुत अच्छा तरीका है। मैं यह इसलिए की तरह उपयोग कर सकते हैंविविध टेम्पलेट्स में शिम्स का उपयोग करने के लिए अधिक संक्षिप्त तरीका?
//
// Shim interface
//
struct Interface {
virtual void print(std::ostream& out) const = 0;
}; // struct Interface
std::ostream& operator<<(std::ostream& out, Interface const& i) {
i.print(out);
return out;
}
template <typename T>
struct IT: public Interface {
IT(T const& t): _t(t) {}
virtual void print(std::ostream& out) const { out << _t; }
T const& _t;
};
template <typename T>
IT<T> shim(T const& t) { return IT<T>(t); }
अब,:
उदाहरण के लिए, एक साधारण शिम का उपयोग करते हैं
void print_impl(Interface const& t);
template <typename T>
void print(T const& t) { print_impl(shim(t)); }
और कोई बात नहीं print_impl
कैसे कार्यान्वित किया जाता है, print
बहुत हल्के रहता है और होना चाहिए रेखांकित किया जाना चाहिए। बहुत आसान।
सी ++ 11 तथापि variadic टेम्पलेट्स परिचय देता है। तब सामान्य आग्रह सी ++ 11 वैरिएडिक टेम्पलेट्स के साथ सभी असुरक्षित सी-वेरिएडिक्स को पुन: कार्यान्वित करना है, यहां तक कि विकिपीडिया भी a printf
implementation के साथ सुझाव देता है। , प्रकार है कि आप वहाँ 3 पैरामीटर प्रिंट, आदि ... यह आसान होगा निर्दिष्ट कर सकते हैं, तो केवल हम इस प्रोटोटाइप के साथ एक समारोह था:
दुर्भाग्य से, विकिपीडिया के कार्यान्वयन स्थितीय तर्क के साथ सौदा नहीं है
void printf_impl(char const* format, Interface const* array, size_t size);
या इसी तरह के।
अब, कैसे हम मूल इंटरफ़ेस से पाटने है:
template <typename... T>
void printf(char const* format, T const&... t);
ऊपर हस्ताक्षर करने के लिए ?
शिम्स के साथ एक कठिनाई यह है कि वे स्थिरांक-रेफरी व्यवहार के लिए बाध्य (गतिशील स्मृति को आबंटित किए बिना सिर्फ पर्याप्त बनाई गई अस्थायी आवरण के जीवन का विस्तार करने के लिए पर भरोसा करते हैं, अगर वे किया था वे नहीं सस्ता होगा)।
यह बाध्यकारी + एक चरण में सरणी परिवर्तन प्राप्त करना मुश्किल लगता है। विशेष रूप से क्योंकि भाषा में संदर्भों (संदर्भों के सूचक) के सरणी की अनुमति नहीं है।
मैं एक समाधान की एक शुरुआत है, उन दिलचस्पी के लिए:
//
// printf (or it could be!)
//
void printf_impl(char const*, Interface const** array, size_t size) {
for (size_t i = 0; i != size; ++i) { std::cout << *(array[i]); }
std::cout << "\n";
}
template <typename... T>
void printf_bridge(char const* format, T const&... t) {
Interface const* array[sizeof...(t)] = { (&t)... };
printf_impl(format, array, sizeof...(t));
}
template <typename... T>
void printf(char const* format, T const&... t) {
printf_bridge(format, ((Interface const&)shim(t))...);
}
हालांकि आप एक अनुपूरक कदम है, जो थोड़ा कष्टप्रद है की शुरूआत नोट करती है। फिर भी, it appears to work।
यदि कोई प्रस्ताव देने के लिए बेहतर कार्यान्वयन करता तो मैं बहुत आभारी रहूंगा।
@Potatoswatter जो helps a bit (कोई वहाँ रेंज के लिए) प्रारंभकर्ता सूचियों, का उपयोग करते हुए सुझाव दिया।
void printf_impl(char const*, std::initializer_list<Interface const*> array) {
for (Interface const* e: list) { std::cout << *e; }
std::cout << "\n";
}
template <typename... T>
void printf_bridge(char const* format, T const&... t) {
printf_impl(format, {(&t)...});
}
लेकिन अभी भी मध्यवर्ती फ़ंक्शन समस्या को हल नहीं करता है।
ओह नोस, तेह ब्लोट्स! मेरे निष्पादन योग्य में कुछ अतिरिक्त केबी मेरी दुनिया का अंत है। – Puppy
@DeadMG इस तरह की चीज वास्तव में मेगाबाइट्स को बचा सकती है। – Potatoswatter
मुझे नहीं लगता कि 'आईटी' में सदस्य चर 'टी कॉन्स & _t;' 'शिम() 'फ़ंक्शन से अस्थायी रूप से लौटाया गया जीवनकाल बढ़ाता है। जब कन्स्ट्रक्टर लौटाता है, तो '_t' विनाशकारी वस्तु को संदर्भित करता है। – Nawaz