नमस्ते, मैं यहां यहांstd::optional कार्यान्वयन में से एक को देख रहा हूं। a> और मैंने पाया है कि यह कोड स्निपेट मुझे भ्रमित करता है:

// workaround: std utility functions aren't constexpr yet
template <class T> inline constexpr T&& constexpr_forward(typename 
std::remove_reference<T>::type& t) noexcept
{
    return static_cast<T&&>(t);
}

तो मैं इसे निम्नलिखित तरीके से नहीं समझता:

  1. typename यहाँ क्या करता है? बस निम्नलिखित भाग घोषित करने के लिए एक प्रकार है?
  2. हमें यहां std::remove_reference की आवश्यकता क्यों है? क्या हमने संदर्भ को वापस type& भाग में नहीं जोड़ा?
  3. "std यूटिलिटी फ़ंक्शंस अभी तक कॉन्स्टेक्स नहीं हैं" का क्या अर्थ है? यह फ़ंक्शन उन्हें constexpr कैसे बनाता है? इसका शरीर सिर्फ एक static_cast है।
  4. यह फ़ंक्शन कई कंस्ट्रक्टरों में उपयोग किया जाता है और यह इस तरह दिखता है: टेम्पलेट <वर्ग... Args> constexpr storage_t(Args&&... args) : value_(constexpr_forward(args)...) {}, तो यह args के लिए यहाँ क्या करता है?

बहुत - बहुत धन्यवाद।

3
Bob Fang 17 जुलाई 2017, 00:33

1 उत्तर

आपको एक कदम पीछे जाना पड़ सकता है और कुछ और पढ़ना पड़ सकता है, यह कोड काफी उन्नत है और आपके प्रश्न इंगित करते हैं कि आपने इनमें से कुछ चीजों को नहीं पढ़ा है। मैं स्कॉट मेयर्स द्वारा आधुनिक प्रभावी सी ++ की अनुशंसा करता हूं। आपके विशिष्ट प्रश्नों के अनुसार:

  1. हां, typename का उपयोग करना आवश्यक है, क्योंकि हम एक टेम्पलेट वर्ग के सदस्य के साथ काम कर रहे हैं, जो एक आश्रित प्रकार है। इसे संकलक को आश्वस्त करने के रूप में सोचें कि यह बात वास्तव में एक प्रकार है, इससे पहले कि संकलक इसे सत्यापित कर सके (क्योंकि टेम्पलेट को तत्काल नहीं किया गया है, केवल परिभाषित किया गया है, इसलिए यह नहीं जानता कि T क्या है )
  2. अधिकांश टेम्प्लेट फ़ंक्शंस के विपरीत, std::forward के साथ विचार टेम्पलेट पैरामीटर को स्पष्ट रूप से निर्दिष्ट करना है ताकि यह सही ढंग से काम कर सके। यह प्रपत्र प्रकार की कटौती को अक्षम करता है जो इस संदर्भ में वांछनीय है (दुर्लभ)। ध्यान दें कि किसी संदर्भ को हटाना और उसे वापस जोड़ना कुछ भी नहीं करने जैसा नहीं है, जैसे कि यह शुरू करने का संदर्भ नहीं है, यह अभी भी एक के रूप में समाप्त होता है। यही लक्ष्य है; हमेशा एक लाभा संदर्भ लेने के लिए।
  3. इसका सीधा सा मतलब है कि वे constexpr चिह्नित नहीं हैं। एक फ़ंक्शन का उपयोग निरंतर अभिव्यक्तियों में किया जा सकता है, यदि इसे constexpr के रूप में चिह्नित किया गया हो। सभी कार्यों को constexpr के रूप में चिह्नित नहीं किया जा सकता है, कुछ प्रतिबंध हैं। मानक पुस्तकालय समारोह std::forward constexpr हो सकता है, लेकिन बस नहीं है। यह फ़ंक्शन उसके लिए सिर्फ एक समाधान है।
  4. यह मूल रूप से std::forward के बराबर है, इसलिए इसके बारे में गूगल करना और इसके बारे में पढ़ना अच्छा होगा, क्योंकि यह ग्रोक करने के लिए एक छोटी सी बात नहीं है (और जिस पुस्तक का मैंने उल्लेख किया है वह इसके बारे में बात करती है)। मूल रूप से विचार यह है कि एक बार जब आपके पास तर्कों के एक सेट को स्वीकार करने वाला कोई कार्य होता है, तो मान लीजिए कि वह उन तर्कों को कहीं और अग्रेषित करना चाहता है। बात यह है कि सभी प्रतीक नाम (इस मामले में, args) को अंतराल माना जाता है (भले ही वे प्रतिद्वंद्विता संदर्भ हैं ... जैसा कि मैंने कहा, यह भ्रमित करने वाला है, प्रकार बनाम मूल्य श्रेणी)। हालाँकि, यदि उपयोगकर्ता किसी भी अस्थायी रूप से पास हुआ है तो हम चाहते हैं कि इसे अगले फ़ंक्शन के लिए सही ढंग से (अर्थात अस्थायी के रूप में) अग्रेषित किया जाए। std::forward सुनिश्चित करता है कि चीजें प्रतिद्वंद्विता के रूप में पारित हो जाती हैं, वापस रैवल्यू संदर्भों में डाली जाती हैं और आंतरिक कार्य द्वारा सही ढंग से उपयोग की जा सकती हैं।

मुझे आशा है कि वह मदद करेंगे। फिर से, आपको मूल्य श्रेणियों की गहरी समझ हासिल करने के लिए कुछ समय पढ़ने की आवश्यकता होगी, और इसे पूरी तरह से पचाने के लिए संदर्भों को प्रतिद्वंद्विता करना होगा।

2
Nir Friedman 17 जुलाई 2017, 00:51