विषय पर बढ़ें

अंतिम अद्यतन:2026-10-12

C++17 optional_ref

यह लेख foonathan के ब्लॉग optional_ref discussion की विवेचना है; मूल लेख इस बात पर सबसे शानदार चर्चा है कि std::optional<T&> (optional संदर्भ) अंततः मानक में क्यों नहीं आया। C++26 की पूर्व-संध्या पर यह विषय फिर उठा, इसलिए मुख्य तर्कों को दोहराना लाभदायक है।

1. समस्या: std::optional compile क्यों नहीं होता?

std::optional<int>, std::optional<std::string> दोनों ठीक हैं, लेकिन std::optional<int&> सीधे compile error देता है। कारण थोड़ा "ऐतिहासिक विरासत" जैसा है: मानक बनाते समय इसकी assignment semantics पर सहमति नहीं बनी, तो मानक में सीधे लिख दिया गया कि T संदर्भ प्रकार होने पर व्यवहार undefined है।

तो एक "संभवतः खाली संदर्भ" में आख़िर कठिन क्या है? लेखक ने चार प्रश्न निचोड़े:

(1) क्या optional<T&> और pointer एक ही चीज़ हैं?

(2) क्या हमें सचमुच optional<T&> चाहिए?

(3) assign करते समय rebind (नए object से फिर बंधना) चाहिए या assign-through (इंगित object में लिखना)?

(4) इसमें assignment operator होना ही चाहिए या नहीं?

लेखक के tl;dr उत्तर: नहीं, नहीं चाहिए, rebind, नहीं होना चाहिए। अब देखें क्यों।

2. optional संदर्भ pointer नहीं है

सहज रूप से "संभवतः खाली संदर्भ" pointer ही है, लेकिन लेखक ने एक और बुनियादी अंतर बताया:

  • T& का निर्माण और पहुँच दोनों implicit हैं: संदर्भ मिलते ही सीधे इस्तेमाल करें, dereference की ज़रूरत नहीं;
  • T* का निर्माण और पहुँच दोनों explicit हैं: &x से पता लेना पड़ता है, *p से dereference करना पड़ता है।

यह explicitness का अंतर मूल्यवान है: pointer आपको याद दिलाता है कि "यहाँ null हो सकता है, aliasing की समस्या हो सकती है"। optional<T&> को हर जगह implicit conversion वाला "अधिक सुविधाजनक pointer" बना देना ठीक इसी सुरक्षा-परत को फेंक देना है। लेखक का निष्कर्ष: अगर आपको "संभवतः खाली" व्यक्त करना है, तो explicit T* बेहतर documentation है।

3. rebind या assign-through

यह पूरी चर्चा का केंद्रीय अवरोध है:

int a = 1, b = 2;
std::optional<int&> opt = a;
opt = b;  // 问题:这句是什么意思?

दो व्याख्याएँ:

  • rebind: opt अब b से बंध गया (संदर्भ की alias semantics; int& ra = a; ra = b; b को a में assign करता है…… रुकिए, int& का assignment तो ठीक assign-through ही है!)
  • assign-through: b का मान a में लिखना (सामान्य संदर्भ T& की semantics)।

विरोधाभास यहीं है: अगर optional संदर्भ T& की semantics से मेल खाना चाहे तो assignment, assign-through होना चाहिए; लेकिन एक mutable optional (जिसमें दूसरा object भी भरा जा सके) सहज रूप से rebind माँगता है। दोनों semantics तर्कसंगत हैं, समिति कोई निष्कर्ष नहीं निकाल पाई, और इस तरह optional<T&> कभी वैध नहीं हुआ।

व्यवहार में rebind semantics चाहिए तो समुदाय का समाधान है अपना optional_ref<T> बनाना: भीतर T* रखते हैं, assignment में सिर्फ pointer बदलते हैं—— semantics बिल्कुल साफ। C++26 का std::optional_ref प्रस्ताव भी यही रास्ता लेता है।

4. सारांश

(1) optional<T&> pointer का syntactic sugar नहीं है; दोनों की explicitness में बुनियादी भूमिका-विभाजन है;

(2) इसे रोकने वाली चीज़ assignment semantics की द्विअर्थकता है: rebind और assign-through दोनों तर्कसंगत लगते हैं;

(3) "शून्य-संभावित संदर्भ" चाहिए तो explicit pointer या optional_ref, "वैध किया गया optional" से ज़्यादा सुरक्षित विकल्प हैं।

अंत में एक प्रश्न: optional<T&> का value() और *opt, T& लौटाए या const T&? और अगर const के रूप में capture की semantics भी व्यक्त करनी हो तो template parameter का डिज़ाइन कैसा हो?

संबंधित विषय

टिप्पणियाँ