वापसी पर स्पष्ट रूपांतरण की अनुमति नहीं है


21
#include <optional>

bool f() {
  std::optional<int> opt;
  return opt;
}

संकलन नहीं है: 'return': cannot convert from 'std::optional<int>' to 'bool'

परामर्श संदर्भ मैंने एक स्पष्टीकरण खोजने के लिए सोचा होगा, लेकिन मैंने इसे पढ़ा क्योंकि यह ठीक होना चाहिए।

जब भी किसी प्रकार T1 की अभिव्यक्ति को उस प्रकार को स्वीकार नहीं किया जाता है, लेकिन किसी अन्य प्रकार के T2 को स्वीकार करता है, तो निहित रूपांतरण किए जाते हैं; विशेष रूप से:

  • जब कोई फ़ंक्शन T2 के साथ पैरामीटर के रूप में घोषित किया जाता है तो कॉल करते समय अभिव्यक्ति का उपयोग तर्क के रूप में किया जाता है;
  • जब अभिव्यक्ति को ऑपरेटर के साथ एक ऑपरेटर के रूप में उपयोग किया जाता है जो T2 की अपेक्षा करता है;
  • जब T2 लौटने वाले फ़ंक्शन में रिटर्न स्टेटमेंट सहित, T2 के नए ऑब्जेक्ट को इनिशियलाइज़ करना;
  • जब एक स्विच स्टेटमेंट में अभिव्यक्ति का उपयोग किया जाता है (टी 2 अभिन्न प्रकार है);
  • जब अभिव्यक्ति का उपयोग इफ स्टेटमेंट या लूप (T2 बूल) में किया जाता है।

7
" अंतर्निहित रूपांतरण प्रदर्शन कर रहे हैं" , लेकिन operator bool()की std::optionalहै explicit
Jarod42

जवाबों:


22

std::optionalअंतर्निहित रूप से परिवर्तित करने के लिए कोई सुविधा नहीं है bool। (अंतर्निहित रूपांतरण को boolआमतौर पर एक बुरा विचार माना जाता है, क्योंकि boolयह एक अभिन्न प्रकार है इसलिए ऐसा कुछ int i = optसंकलन और पूरी तरह से गलत काम करेगा।)

std::optional करता है एक "प्रासंगिक रूपांतरण" bool करने के लिए है, जो की परिभाषा एक डाली ऑपरेटर के समान दिखता है: explicit operator bool()। इसका उपयोग अंतर्निहित रूपांतरणों के लिए नहीं किया जा सकता है; यह केवल कुछ विशिष्ट स्थितियों में लागू होता है जहां अपेक्षित "संदर्भ" एक बूलियन है, जैसे कि अगर-स्टेटमेंट की स्थिति।

आप जो चाहते हैं opt.has_value()


4

C ++ डॉक्स से :

जब वैकल्पिक प्रकार की एक वस्तु <T> को प्रासंगिक रूप से बूल में परिवर्तित किया जाता है, तो रूपांतरण सही होता है यदि ऑब्जेक्ट में कोई मान होता है और यदि उसमें मान नहीं होता है तो वह गलत होता है।

प्रासंगिक रूपांतरणों के बारे में यहाँ पढ़ें :

निम्नलिखित संदर्भों में, प्रकार बूल की अपेक्षा की जाती है और घोषणा बूल टी (ई) यदि निहित रूपांतरण किया जाता है; अच्छी तरह से गठित है (जो कि, एक स्पष्ट रूपांतरण फ़ंक्शन जैसे कि स्पष्ट टी :: ऑपरेटर बूल () कास्ट; माना जाता है)। ऐसी अभिव्यक्ति ई को प्रासंगिक रूप से बूल में परिवर्तित करने के लिए कहा जाता है।

  • यदि, जबकि, के लिए नियंत्रण अभिव्यक्ति;
  • में निर्मित तार्किक ऑपरेटरों के संचालन !, && और ||
  • सशर्त ऑपरेटर का पहला संचालन ;:;
  • एक static_assert घोषणा में विधेय;
  • एक noexcept स्पेसर में अभिव्यक्ति;
  • एक स्पष्ट विनिर्देशक में अभिव्यक्ति;

आप निम्नलिखित हैक कर सकते हैं:

bool f() {
    std::optional<int> opt;
    return opt || false;
}

क्योंकि प्रासंगिक रूपांतरण बिल्ट-इन लॉजिकल ऑपरेटर्स के मामले में होता है, लेकिन प्रासंगिक रूपांतरण में कथन शामिल नहीं होते हैं returnऔर std::optionalस्वयं के पास इनका रूपांतरण नहीं होता है bool

इसलिए, इसका उपयोग करना सबसे अच्छा होगा std::optional<T>::has_value:

bool f() {
    std::optional<int> opt;
    return opt.has_value();
}

किस बारे में return {opt}? याreturn bool{opt};
दिनांक

3
@darune return {opt};काम नहीं करेगा लेकिन return static_cast<bool>(opt);या return bool{opt};काम करेगा। हालाँकि, यह has_valueसदस्य फ़ंक्शन का उपयोग करने का सुझाव दिया गया है क्योंकि यह वास्तव में स्पष्ट इरादा दिखाता है कि आप क्या करना चाहते हैं
NutCracker

या प्रसिद्ध return !!pot;हैक ( has_valueबेहतर है)
LF

1

ऐसा इसलिए है क्योंकि std का निहित दोष :: वैकल्पिक बूल समर्थित नहीं है: https://en.cppreference.com/w/cpp/utility/optional/operator_bool

constexpr स्पष्ट ऑपरेटर बूल () const noexcept;

आपको स्पष्ट रूप से बूल में कनवर्ट करना होगा bool(opt)या opt.has_value()इसके बजाय बस का उपयोग करना होगा।


बूल {ऑप्ट} काम करता है और इसे बूल (ऑप्ट)
डार्यून

1

यह वास्तव में निहित रूपांतरण के बारे में नहीं है, यह आरंभीकरण के प्रकार के बारे में है।

वैकल्पिक क्या है एक स्पष्ट रूपांतरण फ़ंक्शन, यानी

explicit operator bool() const; 

N4849 से [class.conv.fct] / P2

रूपांतरण फ़ंक्शन स्पष्ट हो सकता है (9.2.2), इस स्थिति में इसे केवल प्रत्यक्ष-आरंभीकरण के लिए उपयोगकर्ता द्वारा परिभाषित रूपांतरण माना जाता है।

उपरोक्त का अर्थ है कि ये मामले रूपांतरण फ़ंक्शन का उपयोग करेंगे: [dcl.init] / p16

आरंभिकता (16.1) - एक आरंभिक के लिए जो एक कोष्ठक-अभिव्यक्ति अभिव्यक्ति-सूची या एक ब्रेडेड-इनिट-सूची है, (16.2) - एक नए-आरंभक (7.6.2.7), (16.3) के लिए - एक static_cast अभिव्यक्ति में ( 7.6.1.8), (16.4) - एक कार्यात्मक संकेतन प्रकार में रूपांतरण (7.6.1.3), और (16.5) - एक शर्त के ब्रेडेड-इन-लिस्ट रूप में प्रत्यक्ष-आरंभीकरण कहा जाता है।

हालांकि, ये मामले रूपांतरण फ़ंक्शन का उपयोग नहीं करेंगे: [dcl.init] / p15

एक ब्रेस-या-समतुल्य-इनिशियलाइज़र या स्थिति (8.5) के रूप में, साथ ही साथ तर्क पासिंग, फ़ंक्शन रिटर्न, एक अपवाद (14.2) को फेंकना, एक अपवाद (14.4), और सदस्य आरंभीकरण के रूप में होने वाली आरंभीकरण। (9.4.1), को कॉपी-इनिशियलाइजेशन कहा जाता है।

प्रश्न में उदाहरण प्रतिलिपि आरंभीकरण मामले के अंतर्गत आता है और वैकल्पिक रूपांतरण फ़ंक्शन का उपयोग नहीं करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.