क्या नए C ++ 11 प्रोग्राम के लिए ट्रेलिंग रिटर्न टाइप सिंटैक्स स्टाइल डिफ़ॉल्ट होना चाहिए? [बन्द है]


92

C ++ 11 एक नए फ़ंक्शन सिंटैक्स का समर्थन करता है:

auto func_name(int x, int y) -> int;

वर्तमान में इस समारोह के रूप में घोषित किया जाएगा:

int func_name(int x, int y);

नई शैली अभी तक व्यापक रूप से अपनाई नहीं गई है (gcc stl में कहें)

हालाँकि, क्या इस नई शैली को नए C ++ 11-कार्यक्रमों में हर जगह पसंद किया जाना चाहिए, या क्या इसका उपयोग केवल जरूरत के समय किया जाएगा?

व्यक्तिगत रूप से, मैं जब संभव हो तो पुरानी शैली पसंद करता हूं, लेकिन मिश्रित शैलियों वाला एक कोड-बेस बहुत बदसूरत दिखता है।


29
यह ज्यादातर decltypeतर्कों पर है।
कैट प्लस प्लस

क्या CatPlusPlus कहते हैं: अपने उदाहरण में इसे प्रयोग नहीं ज्यादा समझ में आता है
टिजिन

@ कैट प्लस प्लस इसका मतलब है कि आप चीजों को छोड़ देते हैं क्योंकि वे सी ++ 03 में हैं, जब तक आपको रिटर्न प्रकार प्राप्त करने की आवश्यकता नहीं है?
मर्क

1
हर फ़ंक्शन के सामने "ऑटो" निर्दिष्ट करने के लिए बदसूरत। अजगर की "डीई" के लिए सी ++ की तरह जवाब है?
एरिक एरोनिटी

जवाबों:


109

ऐसे कुछ मामले हैं जहां आपको एक पीछे आने वाले रिटर्न प्रकार का उपयोग करना चाहिए। सबसे विशेष रूप से, एक लैम्ब्डा रिटर्न प्रकार, यदि निर्दिष्ट किया गया है, तो पीछे आने वाले रिटर्न प्रकार के माध्यम से निर्दिष्ट किया जाना चाहिए। इसके अलावा, यदि आपका रिटर्न प्रकार उपयोग करता है decltype, जिसके लिए तर्क नाम के दायरे की आवश्यकता होती है, तो पीछे आने वाले रिटर्न प्रकार का उपयोग किया जाना चाहिए (हालांकि, कोई आमतौर पर declval<T>इस उत्तरार्द्ध मुद्दे के आसपास काम करने के लिए उपयोग कर सकता है )।

अनुगामी वापसी प्रकार के कुछ अन्य मामूली फायदे हैं। उदाहरण के लिए, पारंपरिक फ़ंक्शन सिंटैक्स का उपयोग करके गैर-इनलाइन सदस्य फ़ंक्शन परिभाषा पर विचार करें:

struct my_awesome_type
{
    typedef std::vector<int> integer_sequence;

    integer_sequence get_integers() const;
}; 

my_awesome_type::integer_sequence my_awesome_type::get_integers() const
{
    // ...
}

कक्षा के नाम के पहले प्रकट होने के बाद से सदस्य टाइप किए गए दायरे में नहीं हैं ::get_integers, इसलिए हमें कक्षा की योग्यता को दो बार दोहराना होगा। यदि हम एक पीछे लौटने वाले प्रकार का उपयोग करते हैं, तो हमें टाइप का नाम दोहराने की आवश्यकता नहीं है:

auto my_awesome_type::get_integers() const -> integer_sequence
{
    // ...
}

इस उदाहरण में, यह इतनी बड़ी बात नहीं है, लेकिन यदि आपके पास लंबे समय तक नाम या वर्ग टेम्पलेट के सदस्य फ़ंक्शन हैं जो इनलाइन को परिभाषित नहीं करते हैं, तो यह पठनीयता में बड़ा बदलाव ला सकता है।

C ++ Now 2012 में अपने "फ्रेश पेंट" सत्र में, एलिसडेयर मेरेडिथ ने कहा कि यदि आप लगातार रिटर्न प्रकार का उपयोग करते हैं, तो आपके सभी कार्यों के नाम बड़े करीने से हैं:

auto foo() -> int;
auto bar() -> really_long_typedef_name;

मैं में हर जगह वापसी प्रकार अनुगामी का उपयोग किया है CxxReflect , आप कैसे कोड दिखता है उन्हें लगातार उपयोग का एक उदाहरण के लिए देख रहे अगर ऐसा है, आप एक बार देख वहाँ (जैसे, ले जा सकते हैं वर्ग )।type


1
ऐसा नहीं लगता है कि अभी तक आम सहमति है, लेकिन नई शैली के साथ CxxReflect को देखना दिलचस्प है।
मिरिक

नमस्ते जेम्स। यह उत्तर संभवतः C ++ 14 मानक के प्रकाश में अधिक सटीक बनाया जा सकता है।
ड्रू डॉर्मन

@DrewDormann आप क्या जोड़ेंगे / बदलेंगे?
अंडरस्कोर_ड

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

67

दूसरों ने जो कहा उसके अलावा, अनुगामी रिटर्न प्रकार भी उपयोग करने की अनुमति देता है this, जो अन्यथा अनुमति नहीं है

struct A {
  std::vector<int> a;

  // OK, works as expected
  auto begin() const -> decltype(a.begin()) { return a.begin(); }

  // FAIL, does not work: "decltype(a.end())" will be "iterator", but 
  // the return statement returns "const_iterator"
  decltype(a.end()) end() const { return a.end(); }
};

दूसरी घोषणा में, हमने पारंपरिक शैली का उपयोग किया। हालाँकि चूंकि thisउस स्थिति में अनुमति नहीं है, इसलिए संकलक इसका उपयोग नहीं करता है। इसलिए यह निर्धारित करने a.end()के aलिए सांख्यिकीय रूप से घोषित प्रकार का उपयोग करता है कि यह किस endअधिभार vector<int>को कॉल करने जा रहा है, जो कि नॉन-कास्ट संस्करण होने का अंत करता है।


2
हालांकि यह अवधारणा का एक अच्छा / साफ-सुथरा प्रदर्शन है (वापसी के प्रकारों में सदस्यों का उपयोग करके), यह C ++ 14 के बाद से मज़ेदार है, एक प्रकार को निर्दिष्ट करते हुए एक इनलाइन परिभाषा में पूरी तरह से निरर्थक है जिसमें कोई रूपांतरण नहीं है; अब हम केवल पूर्ण रिटर्न प्रकार कटौती का उपयोग कर सकते हैं। : P
अंडरस्कोर_ड

27

एक अन्य लाभ यह है कि जब फ़ंक्शन फ़ंक्शन को पॉइंटर लौटाता है तो ट्रेलिंग-रिटर्न-टाइप सिंटैक्स अधिक पठनीय हो सकता है। उदाहरण के लिए, तुलना करें

void (*get_func_on(int i))(int);

साथ में

auto get_func_on(int i) -> void (*)(int);

हालाँकि, कोई यह तर्क दे सकता है कि फ़ंक्शन पॉइंटर के लिए एक प्रकार का उपनाम पेश करके बेहतर पठनीयता प्राप्त की जा सकती है:

using FuncPtr = void (*)(int);
FuncPtr get_func_on(int i);

10

इस अच्छे लेख को देखें: http://www.cprogramming.com/c+11/c+11-auto-decltype-return-value-after-function.html इस वाक्यविन्यास का उपयोग करने के लिए बहुत अच्छा उदाहरण है जब खेल में घोषणा के बिना :

class Person
{
public:
    enum PersonType { ADULT, CHILD, SENIOR };
    void setPersonType (PersonType person_type);
    PersonType getPersonType ();
private:
    PersonType _person_type;
};

auto Person::getPersonType () -> PersonType
{
    return _person_type;
}

और एलेक्स एलेन के लेख से शानदार विवरण भी चुराया गया है "क्योंकि रिटर्न वैल्यू फ़ंक्शन के अंत में जाता है, इसके बजाय, इसके पहले आपको क्लास स्कोप को जोड़ने की आवश्यकता नहीं है।"

इस संभावित मामले की तुलना तब करें जब दुर्घटना से एक वर्ग की गुंजाइश भूल जाए, और बड़ी आपदा के लिए, एक अन्य व्यक्ति को वैश्विक दायरे में परिभाषित किया जाए:

typedef float PersonType; // just for even more trouble
/*missing: Person::*/
PersonType Person::getPersonType ()
{
    return _person_type;
}

7
मुझे यकीन नहीं है कि यह "आपदा" श्रेणी में आता है: यदि प्रकार गलत है, तो कोड संकलन नहीं करेगा। रनटाइम त्रुटियों के विनाशकारी परिणाम हो सकते हैं; संकलन-समय त्रुटियों, इतना नहीं।
जेम्स मैकनेलिस

4
@JamesMcNellis कंपाइलर आउटपुट की तुलना करता है: prog.cpp:13:12: error: prototype for 'PersonType Person::getPersonType()' does not match any in class 'Person'बनाम prog.cpp:13:1: error: 'PersonType' does not name a type कंपाइलर से पहली त्रुटि कम से कम मेरे लिए, समझने के लिए बदतर है।
PiotrNycz

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