2010-04-11 9 views
13

मैं निम्नलिखित कोड की तरह कुछ है:कैसे ठीक से variadic टेम्पलेट के साथ संदर्भ का उपयोग करने के लिए

template<typename T1, typename T2, typename T3, typename T4> 
    void inc(T1& t1, T2& t2, T3& t3, T4& t4) { ++t1; ++t2; ++t3; ++t4; } 

    template<typename T1, typename T2, typename T3> 
    void inc(T1& t1, T2& t2, T3& t3) { ++t1; ++t2; ++t3; } 

    template<typename T1, typename T2> 
    void inc(T1& t1, T2& t2) { ++t1; ++t2; } 

    template<typename T1> 
    void inc(T1& t1) { ++t1; } 

मैं आगामी मानक से प्रस्तावित variadic टेम्पलेट का उपयोग कर यह reimplement करना चाहते हैं। हालांकि, मैंने अभी तक जो उदाहरण देखे हैं, वे उदाहरणों की तरह printf प्रतीत होते हैं, यहां अंतर संदर्भों का उपयोग प्रतीत होता है। मैं निम्नलिखित के साथ आ गया है:

inline void inc() { } 

template<typename T> 
inline void inc(T&& t) { ++t; } 

template<typename T,typename ... Args> 
inline void inc(T&& t, Args&& ... args) { ++t; inc(args...); } 

क्या मुझे पता करना चाहते हैं:

  • मैं आर-मूल्यों के बजाय संदर्भ का उपयोग करते हुए किया जाना चाहिए?

  • संभव संकेतों को पूरा करने के तरीके के बारे में संभावित संकेत या संकेत।

  • रिकर्सिव फ़ंक्शन कॉल के मुद्दे के संबंध में नए प्रस्तावित मानक प्रदान करने की क्या गारंटी है, क्या कोई संकेत है कि उपर्युक्त वैरिएड संस्करण मूल के रूप में इष्टतम होगा? (मैं इनलाइन या कुछ ऐसे जोड़ना चाहिए?)

+7

जिज्ञासा से, मैंने उन कार्यों को gcc4.5 पर फेंक दिया, और रिकर्सन हटा दिया गया और पूरी चीज को रेखांकित किया गया। –

+0

'T &&' एक रैल्यू संदर्भ नहीं है क्योंकि यह एक टेम्पलेट पैरामीटर (इस मामले में 'टी') में सफल होता है। इसलिए यह एक सार्वभौमिक संदर्भ/अग्रेषण संदर्भ है जो सबकुछ से जुड़ा हुआ है। 'Arg &&' के लिए भी यही सच है। [विवरण] देखें (http://en.cppreference.com/w/cpp/language/reference#Forwarding_references)। –

उत्तर

12

मैं, यहाँ rvalue संदर्भ का उपयोग नहीं करेंगे, क्योंकि है कि आप rvalues ​​जो इस प्रकार की अतर्कसंगत कोड अनुमति दे सकते हैं करने के लिए बाध्य करने की अनुमति देगा के रूप में:

inc(1); 

तो, मैं नियमित रूप से संदर्भ के साथ चिपके रहते हैं होगा:

template<typename T> 
void inc(T& t) { ++t; } 

template<typename T,typename ... Args> 
void inc(T& t, Args& ... args) { ++t; inc(args...); } 
+2

@ हिप्पिकोडर: मुझे लगता है कि आपने आर सैमुअल को गलत समझा। उन्होंने कहा, "मैं रैल्यू संदर्भों का उपयोग नहीं करूंगा" – sellibitze

+1

@ सेलिबिटज़: मैं देखता हूं, इसलिए छोटे रावल्यू रेफ में इस कोड नमूने के लिए कुछ भी विशेष नहीं जोड़ता है - इसे किसी भी तेज़ या धीमे नहीं बनायेगा। – Hippicoder

+3

चूंकि एक पैरामीटर पैक एक खाली सूची से मेल खाता है, इसलिए इन अधिभार एक तर्क के मामले में संदिग्ध हैं। आपको बेस केस के रूप में 'शून्य inc() {}' का उपयोग करना चाहिए, और अधिकतर अधिभार के बजाय विशेषज्ञता का उपयोग करना बेहतर होगा। – Potatoswatter

2

मैं आर-मूल्यों के बजाय संदर्भ का उपयोग करते हुए किया जाना चाहिए?

आपका मतलब रावल संदर्भ है? नहीं, मुझे उन लोगों के लिए कोई कारण नहीं दिख रहा है।

संभव संकेतों को पूरा करने के तरीके के बारे में संभावित संकेत या संकेत।

आप पहले से ही वहां हैं। आपका कोड वह करना चाहिए जो आप चाहते हैं।

नए प्रस्तावित मानक रिकर्सिव फ़ंक्शन कॉल के मुद्दे को प्रदान करने की गारंटी देता है, क्या कोई संकेत है कि उपर्युक्त वैरिएड संस्करण मूल के रूप में इष्टतम होगा? (क्या मुझे इनलाइन या कुछ ऐसा जोड़ना चाहिए?)

सी ++ मानक किसी भी इनलाइनिंग की गारंटी नहीं देता है। आप यह देख सकते हैं कि कंपाइलर क्या उत्पन्न करता है। यदि आप सब कुछ रेखांकित करना चाहते हैं - जिसमें अधिकतम इंक-कॉल शामिल है - आप अनुरोध के रूप में दोनों कार्यों में एक इनलाइन डाल सकते हैं। आप अपने गैर-variadic टेम्पलेट की तरह कुछ चाहते हैं, आप इसे इस तरह लपेट कर सकते हैं:

inline void inc_impl() {} 

template<typename T, typename...U> 
inline void inc_impl(T& t, U&...u) { ++t; inc_impl(u...); } 

template<typename...T> 
void inc(T&...t) { inc_impl(t...); } 

अब कांग्रेस नहीं है, जबकि इसके कार्यान्वयन से प्रत्येक शायद शामिल होंगे इनलाइन कोई वास्तविक फ़ंक्शन को कॉल जब inc_impl कॉल की इनलाइनिंग किया जाता है - लेकिन फिर, कोई गारंटी नहीं है।

+6

'इनलाइन' वास्तव में इनलाइनिंग पर कोई प्रभाव नहीं पड़ता है। – GManNickG

+1

@ सेलिबिट्ज: मानक मानते हुए ऐसी कोई गारंटी नहीं होती है, क्या सामान्य परिस्थितियों में सक्षम कंपेलरों को मानना ​​उचित होगा, जैसे कि मूल अधिभार संस्करण क्या होता है, इनलाइन इंक की श्रृंखला में कोड के इस तरह के टुकड़े को अनुकूलित करेगा। – Hippicoder

+3

@ हिप्पिकोडर: हाँ, मुझे ऐसा लगता है। एकमात्र ऐसे स्थान जहां कीवर्ड 'इनलाइन' आम तौर पर आवश्यक है, गैर-टेम्पलेट फ़ंक्शंस हैं जिन्हें एकाधिक अनुवाद इकाइयों में उपयोग किया जाना चाहिए क्योंकि इनलाइन आपको प्रत्येक टीयू में परिभाषा डालने की अनुमति देती है जो इनलाइनिंग को आसान बनाता है क्योंकि इसे लिंक- समय अनुकूलन। – sellibitze

1

नए प्रस्तावित मानक रिकर्सिव फ़ंक्शन कॉल के मुद्दे को प्रदान करने की गारंटी देता है, क्या कोई संकेत है कि उपर्युक्त वैरिएड संस्करण मूल के रूप में इष्टतम होगा? (क्या मुझे इनलाइन या कुछ ऐसा जोड़ना चाहिए?)

मानक अनुकूलन की गारंटी नहीं देगा, यह केवल व्यवहार और परिणाम निर्दिष्ट करता है। क्या कार्य कार्यान्वयन की समस्या को रेखांकित किया जाएगा।

वास्तव में, इनलाइन कीवर्ड केवल कंपाइलर के लिए एक संकेत है जिसे अक्सर अनदेखा किया जाता है क्योंकि संकलक बेहतर निर्णय ले सकता है।

अंत में, जी ++ - 4.5 -O2 पर सभी inc कार्यों को पूरी तरह से रेखांकित किया गया। पता नहीं है कि यह वही है जो आप चाहते हैं।

+1

@ केनीटीएम: इनलाइनिंग जो कुछ मैं ढूंढ रहा था वह काफी है, मैं यह स्पष्ट करने की उम्मीद कर रहा था कि प्रमुख कंपाइलर्स (एमएसवीसी, इंटेल और जीसीसी) मूल अधिभार जैसे कॉल को रेखांकित करेंगे। – Hippicoder