2010-06-22 29 views
7

मिनट एल्गोरिथ्म सामान्य रूप से इस तरह व्यक्त किया जाता है:मिनट और सही अग्रेषण

template <typename T> 
const T& min(const T& x, const T& y) 
{ 
    return y < x ? y : x; 
} 

हालांकि, इस प्रपत्र min(a, b) = 0 के निर्माणों की अनुमति नहीं है।

template <typename T> 
T& min(T& x, T& y) 
{ 
    return y < x ? y : x; 
} 

मैं करना चाहते हैं क्या सही अग्रेषण के माध्यम से इन दो भार के एकजुट है:: आप एक अतिरिक्त अधिभार के साथ कि प्राप्त कर सकते हैं

template <typename T> 
T&& min(T&& x, T&& y) 
{ 
    return y < x ? std::forward<T>(y) : std::forward<T>(x); 
} 

हालांकि, जी ++ 4.5.0 min(2, 4) के लिए एक चेतावनी बाहर थूक कि मैं एक अस्थायी के लिए एक संदर्भ वापस। क्या मैंने कुछ गलत किया?


ठीक है, मुझे मिल गया। समस्या सशर्त ऑपरेटर के साथ है। मेरे पहले समाधान में, यदि मैं min(2, 4) पर कॉल करता हूं तो सशर्त ऑपरेटर एक xvalue देखता है और इस प्रकार एक अस्थायी वस्तु उत्पन्न करने के लिए अग्रेषित x से आगे बढ़ता है। बेशक यह संदर्भ के द्वारा वापस करने के लिए खतरनाक होगा! मैं x और y अलग से करने के बजाय पूरे अभिव्यक्ति अग्रेषित करते हैं, संकलक अब शिकायत नहीं करता है:

template <typename T> 
T&& min(T&& x, T&& y) 
{ 
    return std::forward<T>(y < x ? y : x); 
} 

ठीक है, मैं अंकगणित प्रकार :)

#include <type_traits> 

template <typename T> 
typename std::enable_if<std::is_arithmetic<T>::value, T>::type 
min(T x, T y) 
{ 
    return y < x ? y : x; 
} 

template <typename T> 
typename std::enable_if<!std::is_arithmetic<T>::value, T&&>::type 
min(T&& x, T&& y) 
{ 
    return std::forward<T>(y < x ? y : x); 
} 
+0

हम्म यह मुझे लगता है कि आखिरी उदाहरण एफसीडी के अनुसार भी एक अस्थायी बनाता है। लेकिन यह अजीब लगता है: ऐसा लगता है कि 'int &&' को 'int' xvalue पर बाध्य करने के लिए अस्थायी बनाना है ?! मैंने सोचा कि xvalues ​​अज्ञात रावल्यू रेफ हैं जो अस्थायी संदर्भों के बिना रैल्यू संदर्भों से बंधे जा सकते हैं? ऐसा लगता है कि आपके संशोधित कोड के लिए ऐसा नहीं है, है ना? वापसी प्रकार 'int &&' है, और वापसी अभिव्यक्ति एक 'int' xvalue है। संकलक अब इसके लिए चेतावनी क्यों नहीं देता है? –

+0

यदि मैं सही तरीके से '8.5.3' पढ़ता हूं, तो यह कहता है कि यह xvalue के संदर्भ को बाध्य करते समय एक अस्थायी बनाता है:' int x = 0; int && rx = (int &&)x; 'इसी तरह 'std :: move' का उपयोग करते समय। यह इरादा नहीं हो सकता है, मुझे लगता है। –

+0

@ जोहान्स: 8.5.3 का कौन सा हिस्सा आप विशेष रूप से बात कर रहे हैं? – fredoverflow

उत्तर

3

यह मेरे लिए लगता है कि आप समस्या oversimplify करने की कोशिश कर रहे हैं। दुर्भाग्यवश, इसे पूरी तरह से सही करने के लिए निश्चित रूप से गैर-तुच्छ है। यदि आपने N2199 नहीं पढ़ा है, तो ऐसा करने के लिए अब एक अच्छा समय होगा। रावल्यू संदर्भों का विकास जारी है, इसलिए न्यूनतम और अधिकतम का संदर्भ कार्यान्वयन संभवतया बिल्कुल सही नहीं है, लेकिन कम से कम एक सुंदर सभ्य प्रारंभ बिंदु होना चाहिए। चेतावनी: संदर्भ कार्यान्वयन एक बहुत जितना जटिल होगा उतना जटिल है!

+0

ऐसा लगता है कि प्रस्ताव अस्वीकार कर दिया गया था। कोई विचार क्यों? – jalf

+0

@jalf: मुझे संदेह है कि लोगों ने संदर्भ कार्यान्वयन पर देखा, और आतंक में चिल्लाकर भाग गया। :-) –

+0

@ जेरी: व्यावहारिक लगता है :) – jalf

1

के लिए संदर्भ से छुटकारा मिला आप सही अग्रेषण नहीं चाहते हैं, तो आप T& या const T& और कभी भी T&& वापस नहीं करना चाहते हैं। std::forward किसी अन्य फ़ंक्शन के साथ आपके पैरामीटर में से किसी एक को पास करने के लिए डिज़ाइन किया गया है, न कि वापसी मानों के लिए।

मुझे लगता है कि क्या आप चाहते हैं:

template <typename T> 
min(T&& x, T&& y) -> decltype(x) 
{ 
    return y < x ? y : x; 
} 

संपादित करें संदर्भ समस्या झूलते से बचने के लिए:

template <typename T> 
struct dedangle { typedef T type; } 

template <typename T> 
struct dedangle<const T&> { typedef T type; } 

template <typename T, typename U> 
min(T&& x, U&& y) -> dedangle<decltype(0?y:x)>::type 
{ 
    return y < x ? y : x; 
} 

// dedangle is re-usable by max, etc, so its cost is amortized 
+0

मुझे बिल्कुल यकीन नहीं है कि किस प्रकार 'decltype (x) 'है, लेकिन यह या तो' टी' है, जो कि मैं चाहता हूं, या' टी && 'नहीं है, जो आप कहते हैं कि मुझे नहीं करना चाहिए। सही? मानक के – fredoverflow

+0

धारा 14.8.2.1 [temp.deduct.call] टेम्पलेट कार्यों के तर्कों पर होने वाले परिवर्तनों का वर्णन करता है। 'decltype (x)' आसानी से 'int &' या 'const int 'हो सकता है, जबकि रिटर्न प्रकार इस प्रक्रिया से गुजरता नहीं है। मानक के उस खंड के भीतर उदाहरण # 3 देखें। –

+0

मैं असहमत हूं, 'decltype (x) 'हमेशा' T && 'जैसा ही है। आप 'static_assert (std :: is_same :: value," ouch ");' min' फ़ंक्शन टेम्पलेट में पंक्ति डालकर स्वयं को समझ सकते हैं। – fredoverflow

संबंधित मुद्दे