निम्नलिखित कोड पर विचार करें? N3797 के अपने प्रतिलिपि में यहसमेकन की प्रारंभिक सूची: जब यह कॉपी कन्स्ट्रक्टर का आह्वान कर सकता है?</p> <pre><code>struct A { int x; }; int main() { A a; A b{a}; } </code></pre> <p>इस कार्यक्रम सी ++ 11 मानक में अच्छी तरह से गठित है:
8.5.4 सूची प्रारंभ कहते
[dcl.init.list]
3: इस प्रकार एक वस्तु या प्रकार
T
के संदर्भ की सूची-प्रारंभ परिभाषित किया गया है:
- अगरT
एक समग्र है, कुल प्रारंभिक प्रदर्शन किया जाता है (8.5.1)।
- अन्यथा,T
std::initializer_list<E>
का एक विशेषज्ञता है, ...
- अन्यथा, यदिT
एक वर्ग प्रकार है, तो रचनाकारों पर विचार किया जाता है। लागू कन्स्ट्रक्टर की गणना की जाती है और अधिभार संकल्प का उपयोग करके सबसे अच्छा चुना जाता है। यदि किसी भी प्रकार को बदलने के लिए एक संकीर्ण रूपांतरण की आवश्यकता है, तो कार्यक्रम खराब हो गया है।
- अन्यथा, यदि प्रारंभकर्ता सूची मेंE
प्रकार का एक तत्व है और या तोT
संदर्भ प्रकार नहीं है या यह संदर्भE
से संबंधित है, तो ऑब्जेक्ट या संदर्भ उस तत्व से प्रारंभ किया गया है; यदि तत्व कोT
में परिवर्तित करने के लिए एक संकीर्ण रूपांतरण की आवश्यकता है, तो प्रोग्राम खराब हो गया है।
- अन्यथा, यदिT
एक संदर्भ प्रकार है, तोT
द्वारा प्रकार संदर्भ का एक pr-value अस्थायी है प्रतिलिपि-प्रारंभिक या प्रत्यक्ष-सूची-प्रारंभिक, संदर्भ के प्रारंभिक प्रकार के आधार पर, और संदर्भ है उस अस्थायी के लिए बाध्य।
- अन्यथा, अगर प्रारंभकर्ता सूची में कोई तत्व नहीं है, तो वस्तु मान-प्रारंभिक है।
- अन्यथा, कार्यक्रम खराब गठित है।
उदाहरण का बिंदु यह है कि प्रकार एक समग्र है, लेकिन सूची-प्रारंभिक प्रतिलिपि प्रतिलिपि बनाने का अनुमान है। gcc 4.8
और gcc 4.9
, सी ++ 11 मानक पर, यह विफल रहता है:
main.cpp: In function ‘int main()’:
main.cpp:7:8: error: cannot convert ‘A’ to ‘int’ in initialization
A b{a};
^
और A is not convertible to int
या इसी तरह कहते हैं, क्योंकि कुल प्रारंभ विफल रहता है। gcc 5.4
पर, यह C++ 11 मानक पर ठीक काम करता है।
clang
पर आपको clang-3.5
, 3.6
के साथ समान त्रुटियां मिलती हैं, और यह clang-3.7
पर काम करना शुरू कर देती है।
मैं समझता हूं कि यह सी ++ 14 मानक पर अच्छी तरह से गठित है, और यह एक दोष रिपोर्ट here में उल्लिखित है।
हालांकि, मुझे समझ में नहीं आता है कि इसे मानक में दोष क्यों माना जाता है।
जब मानक लिखते हैं,
"अगर X
, foo-प्रारंभ किया जाता है। अन्यथा, यदि Y
, बार-प्रारंभ किया जाता है, .... नहीं तो, कार्यक्रम बीमार ही बना है।",
इसका मतलब यह नहीं है कि अगर X
रखता है, लेकिन foo-startization निष्पादित नहीं किया जा सकता है, तो हमें जांच करनी चाहिए कि Y
है, और फिर बार-प्रारंभ करने का प्रयास करें?
यह उदाहरण काम करेगा, क्योंकि जब कुल प्रारंभिक विफलता होती है, तो हम std::initializer_list
से मेल नहीं खाते हैं, और अगली स्थिति हम मेल खाते हैं "T
एक वर्ग प्रकार है", और फिर हम निर्माता पर विचार करते हैं।
ध्यान दें कि यह यह कैसे इस संशोधित उदाहरण में काम करता है होना प्रतीत होता है
struct A {
int x;
};
int main() {
A a;
const A & ref;
A b{ref};
}
सभी एक ही compilers इस पहले उदाहरण के रूप में एक ही तरह से व्यवहार करते हैं, पर सी ++ 11 और सी ++ 14 मानकों। लेकिन ऐसा लगता है कि सीडब्ल्यूजी दोष रिकॉर्ड से संशोधित शब्द इस मामले पर लागू नहीं होता है। यह लिखा है:
तो
T
एक वर्ग प्रकार है और प्रारंभकर्ता सूची प्रकारcv T
या एक वर्ग प्रकारT
से प्राप्त की एक एकल तत्व है, उद्देश्य यह है कि तत्व से आरंभ नहीं हो जाता।
http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1467
लेकिन दूसरे कोड के उदाहरण में, प्रारंभकर्ता सूची तकनीकी रूप से const T &
शामिल हैं। इसलिए मैं नहीं देखता कि यह कैसे काम करेगा जब तक कि कुल प्रारंभिक विफल होने के बाद, हमें रचनाकारों का प्रयास करना चाहिए।
क्या मैं गलत हूँ? क्या कुल प्रारंभिक विफल होने के बाद इसे रचनाकारों का प्रयास नहीं करना चाहिए?
यहाँ एक संबंधित उदाहरण है:
#include <iostream>
struct B {
int x;
operator int() const { return 2; }
};
int main() {
B b{1};
B c{b};
std::cout << c.x << std::endl;
}
clang-3.6
, gcc-4.8
, gcc-4.9
में, यह 2
प्रिंट, और clang-3.7
में, gcc-5.0
यह 1
प्रिंट करता है।
मान लीजिए कि मैं गलत हूं, और सी ++ 11 मानक पर, कुल मिलाकर प्रारंभिक सूची को प्रारंभिक प्रारंभिक माना जाना चाहिए और कुछ भी नहीं, जब तक कि दोष रिपोर्ट में नया शब्द पेश नहीं किया जाता है, क्या यह एक बग है तब भी होता है जब मैं नए कंपाइलर्स पर -std=c++11
का चयन करता हूं?
तो आप 'संरचना बी' उदाहरण के बारे में क्या सोचते हैं? आपको लगता है कि 'जीसीसी' और 'क्लैंग' कुछ सी ++ 14 फीचर का उपयोग कर रहे हैं जो सी ++ 11 मानक में उपलब्ध नहीं होना चाहिए? –
@ क्रिसबैक: मुझे लगता है कि उन्होंने फैसला किया है कि यह सी ++ 11 मानक में स्पष्ट दोष था, और उन्होंने निश्चित संस्करण लागू किया है। मुझे संदेह है कि इसे "हल" करने का एकमात्र कारण यह नहीं था कि उन्होंने सी ++ को बहुत तेज़ रिलीज़ करना शुरू कर दिया है, इसलिए पुराने मानकों में दोषों को ठीक करने के बजाय, वे इसे नवीनतम में ठीक कर देते हैं। –