c++ - फ़ंक्शन से 'कॉन्स्ट' के रूप में लौटते समय आदिम और यूजर-डिफ़ाइंड प्रकार अलग-अलग क्यों करते हैं?




c++11 overloading (3)

#include <iostream>

using namespace std;

template<typename T>
void f(T&&) { cout << "f(T&&)" << endl; }

template<typename T>
void f(const T&&) { cout << "f(const T&&)" << endl; }

struct A {};
const A g1() { return {}; }
const int g2() { return {}; }

int main()
{
    f(g1()); // outputs "f(const T&&)" as expected.
    f(g2()); // outputs "f(T&&)" not as expected.
}

मुद्दा वर्णन कोड में एम्बेडेड है। मेरा कंपाइलर clang 5.0

मैं बस विचार करता हूँ:

ऐसे मामलों में सी ++ का अंतर्निहित प्रकार और कस्टम प्रकार भिन्न तरीके से क्यों व्यवहार करता है?


फ़ंक्शन से 'कॉन्स्ट' के रूप में लौटते समय आदिम और यूजर-डिफ़ाइंड प्रकार अलग-अलग क्यों करते हैं?

चूंकि const को कार्यों से लौटा आदिम प्रकारों से हटा दिया गया है। यहाँ पर क्यों:

§ 5 Expressions [expr] से सी ++ 11 में § 5 Expressions [expr] (पृष्ठ 84):

8

जब भी किसी ग्लोबल एक्सप्रेशन को उस ऑपरेटर के ऑपरेंड के रूप में प्रतीत होता है जो उस ऑपरेंड के लिए एक प्राइवेट की अपेक्षा करता है, तो लावल्यू-टू-रैवल्यू (4.1), सरणी-टू-पॉइंटर (4.2), या फ़ंक्शन-टू-पॉइंटर (4.3) मानक रूपांतरण अभिव्यक्ति को एक प्राइव्यू में कनवर्ट करने के लिए लागू किया गया [नोट: क्योंकि सीवी-क्वालीफायर्स को गैर-क्लास प्रकार की अभिव्यक्ति के प्रकार से निकाल दिया जाता है जब अभिव्यक्ति को एक प्राइव्यू में कनवर्ट किया जाता है, उदाहरण के लिए, एक प्रकार का गुणांक का एक लावल्यू अभिव्यक्ति हो सकती है, उदाहरण के लिए, जहां प्रांतीय अभिव्यक्ति का प्रकार int आवश्यक है। -नोट नोट]

और इसी तरह § 5.2.3 Explicit type conversion (functional notation) [expr.type.conv] (पृष्ठ 95):

2

अभिव्यक्ति टी (), जहां टी एक साधारण-प्रकार का विशिष्ट अग्नि या गैर-सरणी पूर्ण ऑब्जेक्ट प्रकार या (संभवतः सीवी-योग्यता) शून्य प्रकार के लिए विशिष्ट नाम है, विशिष्ट प्रकार का एक प्राइव्यू बनाता है, जो कि मूल्यवर्धित होता है ( 8.5; शून्य () मामले के लिए कोई प्रारंभ नहीं किया गया है)। [नोट: यदि टी एक गैर-क्लास प्रकार है जो सीवी-योग्यता है, तो सीवी-क्वालीफायर्स को नज़रअंदाज़ कर दिया जाता है, जिसके परिणामस्वरूप प्राइव्यू (3.10) के प्रकार का निर्धारण करते समय -नोट नोट]

इसका अर्थ यह है कि g2() द्वारा लौटाए गए कंसल्टियल प्रोजेक्ट को प्रभावी रूप से int रूप में माना जाता है


पिछले उत्तर पूरी तरह से मान्य हैं। मैं बस एक संभावित प्रेरणा जोड़ना चाहता हूं क्योंकि कभी-कभी const वस्तुओं को वापस करने के लिए उपयोगी हो सकता है। निम्नलिखित उदाहरण में, class A , class A class C से आंतरिक डेटा पर एक दृश्य देता class C , जो कुछ मामलों में संशोधनीय नहीं होगा (अस्वीकरण, संक्षिप्तता के लिए कुछ आवश्यक भाग छोड़ दिए गए हैं - इस व्यवहार को लागू करने के लिए संभावित रूप से आसान तरीके भी हैं):

class A {
    int *data;
    friend class C; // allow C to call private constructor
    A(int* x) : data(x) {}
    static int* clone(int*) {
        return 0; /* should actually clone data, with reference counting, etc */
    }
public:
    // copy constructor of A clones the data
    A(const A& other) : data(clone(other.data)) {}
    // accessor operators:
    const int& operator[](int idx) const { return data[idx]; }
    // allows modifying data
    int& operator[](int idx) { return data[idx]; }
};

class C {
    int* internal_data;
public:
    C() : internal_data(new int[4]) {} // actually, requires proper implementation of destructor, copy-constructor and operator=
    // Making A const prohibits callers of this method to modify internal data of C:
    const A getData() const { return A(internal_data); }
    // returning a non-const A allows modifying internal data:
    A getData() { return A(internal_data); }
};

int main()
{
    C c1;
    const C c2;

    c1.getData()[0] = 1; // ok, modifies value in c1
    int x = c2.getData()[0]; // ok, reads value from c2
    // c2.getData()[0] = 2;  // fails, tries to modify data from c2
    A a = c2.getData(); // ok, calls copy constructor of A
    a[0] = 2; // ok, works on a copy of c2's data
}

मेरे पास मानक से एक उद्धरण नहीं है, लेकिन cppreference मेरे संदेह की पुष्टि करता है:

गैर-वर्गीय गैर-सरणी प्रत्याशित सीवी-योग्य नहीं हो सकता (नोट: फ़ंक्शन कॉल या कास्ट एक्सप्रेशन के परिणामस्वरूप गैर-श्रेणी के सीवी-योग्य प्रकार की प्रकृति हो सकती है, लेकिन सीवी-क्वालिफायर तुरंत छीन लिया जाता है।)

लौटाए गए कंटेट int सिर्फ एक सामान्य int प्रावल्यूज़ है, और गैर-कॉन्स्ट ओवरलोड को const से एक बेहतर मैच बना देता है।





overload-resolution