रूपांतरण ऑपरेटर का यह अधिभार क्यों चुना जाता है?


27

निम्नलिखित कोड पर विचार करें ।

struct any
{
    template <typename T>
    operator T &&() const;

    template <typename T>
    operator T &() const;
};
int main()
{
    int a = any{};
}

यहां दूसरा रूपांतरण ऑपरेटर को अधिभार संकल्प द्वारा चुना गया है। क्यों?

जहां तक ​​मैं इसे समझता हूं, दो ऑपरेटरों को क्रमशः operator int &&() constऔर कटौती की जाती operator int &() constहै। दोनों व्यवहार्य कार्यों के सेट में हैं। [Over.match.best] के माध्यम से पढ़ने से मुझे यह पता लगाने में मदद नहीं मिली कि उत्तरार्द्ध क्यों बेहतर है।

पूर्व की तुलना में बाद का कार्य क्यों बेहतर है?


मैं एक साधारण बिल्ली हूं और मैं कहूंगा कि यह दूसरी बार होगा क्योंकि दूसरे का परिचय C ++ 11 में एक ब्रेकिंग चेंज होगा। यह कहीं मानक में होगा। हालांकि अच्छा सवाल है, एक उत्थान है। (ध्यान दें विशेषज्ञ: अगर यह टिप्पणी hogwash है तो कृपया मुझे बताएं!)
बतशेबा

3
FWIW, template <typename T> operator T &&() const &&; template <typename T> operator T &() const &;इसे पहले वाले को कॉल करने के लिए मिलता है।
नाथनऑलिवर

5
@LightnessRaceswithMonica रूपांतरण ऑपरेटर इसे अनुमति देते हैं अन्यथा एकाधिक रूपांतरण ऑपरेटरों के लिए कोई रास्ता नहीं होगा।
नाथनऑलिवर 16

1
@ बाथशीबा मुझे नहीं लगता कि यही वजह है। यह कहने जैसा है कि मूव कंस्ट्रक्शनर्स को कभी भी ओवरलोड रेजोल्यूशन द्वारा नहीं चुना जा सकता है क्योंकि यह ब्रेकिंग चेंज होगा। यदि आप मूव कंस्ट्रक्टर लिखते हैं, तो आप अपने कोड को उस परिभाषा के अनुसार "टूट" रहे हैं।
ब्रायन

1
@LightnessRaceswithMonica जिस तरह से मैं इसे सीधे अपने सिर में रखता हूं, मैं फ़ंक्शन के नाम के रूप में वापसी प्रकार का इलाज कर रहा हूं। अलग-अलग तरह के नाम अलग-अलग नाम की सफलता के बराबर होते हैं :)
नथानऑलवर

जवाबों:


13

रूपांतरण ऑपरेटर जो वापस लौटता T&है उसे पसंद किया जाता है क्योंकि यह रूपांतरण करने वाले ऑपरेटर की तुलना में अधिक विशिष्ट होता है T&&

देखें सी ++ 17 [temp.deduct.partial] / (3.2):

रूपांतरण फ़ंक्शन के लिए कॉल के संदर्भ में, रूपांतरण फ़ंक्शन टेम्पलेट के रिटर्न प्रकार का उपयोग किया जाता है।

और / 9:

हैं, तो एक दिया प्रकार के लिए, कटौती दोनों दिशाओं में सफल होता है और दोनों (यानी, प्रकार ऊपर परिवर्तनों के बाद एक जैसे हैं) Pऔर Aसंदर्भ प्रकार थे (प्रकार से बदला जा रहा से पहले ऊपर कहा गया है): - यदि तर्क टेम्पलेट से प्रकार एक लैवल्यू संदर्भ था और पैरामीटर टेम्पलेट से प्रकार नहीं था, पैरामीटर प्रकार को कम से कम तर्क प्रकार के रूप में विशेष नहीं माना जाता है; ...


12

घटाया गया वापसी मूल्य रूपांतरण ऑपरेटर थोड़ा अजीब हैं। लेकिन मूल विचार यह है कि यह एक फंक्शन पैरामीटर की तरह काम करता है जिसे चुनने के लिए इसका उपयोग किया जाता है।

और जब बीच तय T&&और अधिभार संकल्प नियमों में जीत। यह अनुमति है:T&T&

template<class T>
void f( T&& ) { std::cout << "rvalue"; }
template<class T>
void f( T& ) { std::cout << "lvalue"; }

काम करने के लिए। T&&एक लैवल्यू के खिलाफ मैच कर सकता है, लेकिन जब लैवल्यू और सार्वभौमिक संदर्भ ओवरलोड उपलब्ध होते हैं, तो लैवल्यू एक को प्राथमिकता दी जाती है।

रूपांतरण ऑपरेटरों का सही सेट संभवतः है:

template <typename T>
operator T&&() &&;

template <typename T>
operator T &() const; // maybe &

या और भी

template <typename T>
operator T() &&;

template <typename T>
operator T &() const; // maybe &

आपको काटने से जीवन भर के विस्तार को रोकने के लिए।

3 आदेश को निर्धारित करने के लिए उपयोग किए जाने वाले प्रकार उस संदर्भ पर निर्भर करते हैं जिसमें आंशिक ऑर्डर किया जाता है:

[कटाव]

(3.2) रूपांतरण फ़ंक्शन के लिए कॉल के संदर्भ में, रूपांतरण फ़ंक्शन टेम्पलेट के रिटर्न प्रकार का उपयोग किया जाता है।

जब अधिभार उठाते समय "अधिक विशिष्ट" नियमों के आधार पर समाप्त होता है:

(9.1) यदि तर्क टेम्पलेट से प्रकार एक अंतराल संदर्भ था और पैरामीटर टेम्पलेट से प्रकार नहीं था, तो पैरामीटर प्रकार को कम से कम तर्क प्रकार के रूप में विशेष नहीं माना जाता है; अन्यथा,

इस प्रकार operator T&&कम से कम के रूप में विशेष operator T&नहीं है, इस बीच कोई नियम राज्यों के operator T&रूप में कम से कम विशेष नहीं है operator T&&, इसलिए operator T&की तुलना में अधिक विशिष्ट है operator T&&

अधिक विशिष्ट टेम्पलेट कम से अधिक सब कुछ पर समान रूप से अधिभार संकल्प जीतते हैं।


जैसा कि मैं जवाब दे रहा था, किसी ने भाषा-वकील का टैग जोड़ा ; मैं बस हटा सकता है। मेरे पास पाठ पढ़ने की एक अस्पष्ट स्मृति है जो बताती है कि इसे लेने के लिए एक पैरामीटर के रूप में व्यवहार किया जाता है जिसे एक कहा जाता है, और वह पाठ जो बात करता है कि टेम्पलेट ओवरलोड को उठाते समय कैसे &&बनाम &का इलाज किया जाता है, लेकिन सटीक पाठ को छेड़ने में कुछ समय लगेगा। ।
यक - एडम नेवरामोंट

4

हम एक intसे शुरू करने की कोशिश कर रहे हैं any। इसके लिए प्रक्रिया:

  1. सभी तरह से हम ऐसा कर सकते हैं। अर्थात्, हमारे सभी उम्मीदवारों का निर्धारण करें। ये गैर-स्पष्ट रूपांतरण कार्यों से आते हैं जिन्हें intएक मानक रूपांतरण अनुक्रम ( [over.match.conv] ) के माध्यम से परिवर्तित किया जा सकता है । अनुभाग में यह वाक्यांश शामिल है:

    "संदर्भ" के लिए लौटने वाले रूपांतरण फ़ंक्शन के लिए एक कॉल Xप्रकार का एक चमक है X, और इसलिए ऐसे रूपांतरण फ़ंक्शन को Xउम्मीदवार कार्यों के चयन की इस प्रक्रिया के लिए उपज माना जाता है ।

  2. सबसे अच्छा उम्मीदवार चुनें।

चरण 1 के बाद, हमारे पास दो उम्मीदवार हैं। operator int&() constऔर operator int&&() const, जिनमें से दोनों को intउम्मीदवार के कार्यों के चयन के प्रयोजनों के लिए उपज माना जाता है । कौन सा सबसे अच्छा उम्मीदवार है int?

हमारे पास एक टाईब्रेकर है जो लवल्यू संदर्भों को प्रचलित संदर्भों ( [over.ics.rank] / 3/3.3 ) के लिए पसंद करता है। हम वास्तव में यहाँ एक संदर्भ को नहीं बाँध रहे हैं, और उदाहरण कुछ उलटा है - यह उस मामले के लिए है जहाँ पैरामीटर एक अंतराल बनाम रेवल्यू संदर्भ है।

यदि यह लागू नहीं होता है, तो हम अधिक विशिष्ट फ़ंक्शन टेम्पलेट को प्राथमिकता देने के लिए [over.match.best] /2.5 टाईब्रेकर के माध्यम से आते हैं ।

सामान्यतया, अंगूठे का नियम अधिक विशिष्ट रूपांतरण सबसे अच्छा मैच है। लैवल्यू संदर्भ रूपांतरण फ़ंक्शन अग्रेषण संदर्भ रूपांतरण फ़ंक्शन की तुलना में अधिक विशिष्ट है, इसलिए इसे पसंद किया जाता है। intहम इस बात के बारे में कुछ नहीं कर रहे हैं कि हमें एक प्रतिद्वंद्विता की आवश्यकता है (यदि हम इसके बजाय एक को प्रारंभ कर रहे हैं int&&, तो operator T&() constउम्मीदवार नहीं होंगे)।


३.२.३ वास्तव में कहता है कि T&&जीतता नहीं है? आह, लेकिन हमारे पास करने के लिए बाध्य नहीं है। या हम करते हैं? हमारे उम्मीदवारों को उठाते समय कुछ शब्दों को परिभाषित करना चाहिए कि हमें कैसे मिला int&और int&&क्या यह एक बाध्यकारी था?
यक - एडम नेवरामोंट

@ यक-आदमनेवरुमोंट नहीं, कि एक लवल्यू के संदर्भ में प्रचलित संदर्भ हैं। मुझे लगता है कि यह शायद गलत खंड है, और "अधिक विशिष्ट" टाईब्रेकर सही है।
बैरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.