फ़ंक्शन तर्क के रूप में {} क्यों अस्पष्टता का कारण नहीं बनता है?


20

इस कोड पर विचार करें:

#include <vector>
#include <iostream>

enum class A
{
  X, Y
};

struct Test
{
  Test(const std::vector<double>&, const std::vector<int>& = {}, A = A::X)
  { std::cout << "vector overload" << std::endl; }

  Test(const std::vector<double>&, int, A = A::X)
  { std::cout << "int overload" << std::endl; }
};

int main()
{
  std::vector<double> v;
  Test t1(v);
  Test t2(v, {}, A::X);
}

https://godbolt.org/z/Gc_w8i

यह प्रिंट:

vector overload
int overload

अस्पष्ट अधिभार संकल्प के कारण यह संकलन त्रुटि क्यों नहीं उत्पन्न करता है? यदि दूसरा निर्माणकर्ता हटा दिया जाता है, तो हम vector overloadदो बार मिलते हैं । कैसे / किस मेट्रिक से intएक स्पष्ट रूप से बेहतर मैच {}है std::vector<int>?

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


यदि मैं {}कोड के ब्लॉक के रूप में मुख्य रूप से याद करता हूं , तो चर को 0 असाइन करता है - उदाहरण: const char x = {}; 0 पर सेट है (शून्य चार), इंट आदि के लिए समान
सेटी

2
@ सेती जो {}कुछ विशेष मामलों में प्रभावी ढंग से करती है, लेकिन यह आम तौर पर सही नहीं है (शुरुआत, std::vector<int> x = {};काम करने के लिए, std::vector <int> x = 0;नहीं करता है)। यह उतना आसान नहीं है जितना कि " {}शून्य प्रदान करता है"।
मैक्स लैंगहॉफ

सही है, यह इतना आसान नहीं है, लेकिन यह अभी भी शून्य प्रदान करता है - मुझे लगता है कि मुझे लगता है कि यह बीवर काफी भ्रामक है और वास्तव में इस्तेमाल नहीं किया जाना चाहिए
सेटी

2
@ एसटीआई struct A { int x = 5; }; A a = {};किसी भी मायने में शून्य नहीं देता है, यह एक के Aसाथ निर्माण करता है a.x = 5। यह इसके विपरीत है A a = { 0 };, जो कि a.x0. को इनिशियलाइज़ करता है। जीरो इन-लेस नहीं है {}, यह अंतर्निहित है कि प्रत्येक प्रकार डिफ़ॉल्ट रूप से निर्मित या वैल्यू-इनिशियलाइज़्ड कैसे होता है। यहाँ , यहाँ और यहाँ देखें ।
मैक्स लैंगहोफ

मुझे अब भी लगता है कि डिफ़ॉल्ट-निर्मित मूल्य भ्रमित कर रहे हैं (आपको व्यवहार की जांच करने या हर समय बहुत ज्ञान रखने की आवश्यकता है)
सेटी

जवाबों:


12

यह [over.ics.list] में है , मेरा जोर

6 अन्यथा, यदि पैरामीटर एक गैर-एग्रीगेट वर्ग X है और प्रति ओवरलोड प्रस्ताव [over.match.list] तर्क एक्सवाइज़र सूची से टाइप X के ऑब्जेक्ट के आरंभीकरण को निष्पादित करने के लिए X का एकल सर्वश्रेष्ठ निर्माता C चुनता है:

  • यदि C एक इनिशियलाइज़र-लिस्ट कन्स्ट्रक्टर नहीं है और इनिशियलाइज़र लिस्ट में cv U का एक ही एलिमेंट है, जहाँ U, X है या X से एक क्लास है, तो निहित कन्वर्सेशन सीक्वेंस में Ex का मिलान रैंक है अगर U, X या कन्वर्ज़न रैंक है तो U, X से लिया गया है।

  • अन्यथा, निहित रूपांतरण अनुक्रम एक उपयोगकर्ता-परिभाषित रूपांतरण अनुक्रम है जो दूसरे मानक रूपांतरण अनुक्रम एक पहचान रूपांतरण है।

9 अन्यथा, यदि पैरामीटर प्रकार एक वर्ग नहीं है:

  • [...]

  • यदि प्रारंभिक सूची में कोई तत्व नहीं है, तो निहित रूपांतरण अनुक्रम पहचान रूपांतरण है। [ उदाहरण:

    void f(int);
    f( { } ); // OK: identity conversion

    अंत उदाहरण]

std::vectorनिर्माता और बोल्ड यह एक उपयोगकर्ता परिभाषित converison समझे में गोली से आरंभ नहीं हो जाता। इस बीच, एक के लिए int, यह पहचान रूपांतरण है, इसलिए यह पहली c'tor की रैंक को रौंद देता है।


हां, सटीक लगता है।
कोलंबो

यह देखना दिलचस्प है कि इस स्थिति को स्पष्ट रूप से मानक माना जाता है। मुझे वास्तव में उम्मीद थी कि यह अस्पष्ट होगा (और ऐसा लगता है कि यह आसानी से उस तरह से निर्दिष्ट किया जा सकता था)। मैं अपने अंतिम वाक्य में तर्क का पालन नहीं कर सकते - 0प्रकार है intलेकिन टाइप नहीं std::vector<int>, कैसे है कि एक "के रूप में यदि" के "untyped" प्रकृति के wrt {}?
मैक्स लैंगहोफ़

@MaxLanghof - इसे देखने का दूसरा तरीका यह है कि गैर-वर्ग प्रकारों के लिए, यह किसी भी खंड द्वारा उपयोगकर्ता द्वारा परिभाषित रूपांतरण नहीं है। इसके बजाय यह डिफ़ॉल्ट मूल्य के लिए एक सीधा इनिशलाइज़र है। इसलिए इस मामले में एक पहचान।
स्टोरीटेलर -

वह हिस्सा साफ है। मैं उपयोगकर्ता द्वारा परिभाषित रूपांतरण की आवश्यकता से आश्चर्यचकित हूं std::vector<int>। जैसा कि आपने कहा, मुझे उम्मीद थी "पैरामीटर का प्रकार यह तय करता है कि तर्क का प्रकार क्या है", और एक {}"प्रकार" (इसलिए बोलने के लिए) std::vector<int>को प्रारंभ करने के लिए (गैर-पहचान) रूपांतरण की आवश्यकता नहीं होनी चाहिए std::vector<int>। मानक स्पष्ट रूप से यह कहते हैं, ऐसा है, लेकिन यह मेरे लिए कोई मतलब नहीं है। (माइंड यू, मैं यह तर्क नहीं दे रहा हूं कि आप या मानक गलत हैं, बस इसे अपने मानसिक मॉडल के साथ सामंजस्य बिठाने की कोशिश कर रहा हूं।)
मैक्स लैंगहोफ

ठीक है, वह संपादन वह संकल्प नहीं था जिसकी मुझे उम्मीद थी, लेकिन काफी हद तक सही है। : D आपके समय के लिए धन्यवाद!
मैक्स लैंगहोफ़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.