2012-12-30 20 views
10

निम्नलिखित कोड जीसीसी 4.7.2 या बजना 3.2 में संकलन नहीं करता है:वर्दी प्रारंभिकरण का उपयोग कर std :: vector <std :: function <void()>> कॉपी नहीं कर सकता। क्या ये सही है?

#include <vector> 
#include <functional> 

int main() 
{ 
    std::vector<std::function<void()>> a; 
    std::vector<std::function<void()>> b{a}; 
} 

मुद्दा है कि संकलक, एक initializer_list का उपयोग करते समय स्पष्ट रूप से यह सिर्फ नकल निर्माता बुला जाना चाहिए ख बनाने की कोशिश करेंगे। हालांकि यह वांछित व्यवहार प्रतीत होता है क्योंकि मानक कहता है कि प्रारंभकर्ता_सूची रचनाकारों को प्राथमिकता लेनी चाहिए।

यह कोड अन्य std :: vector के लिए ठीक काम करेगा, लेकिन std :: function के लिए संकलक यह नहीं जान सकता कि आप प्रारंभकर्ता_सूची निर्माता या किसी अन्य को चाहते हैं या नहीं।

ऐसा लगता है कि इसके चारों ओर एक रास्ता नहीं है, और यदि ऐसा है तो आप कभी भी टेम्पलेट कोड में वर्दी प्रारंभिक उपयोग नहीं कर सकते हैं। जो एक विशाल शर्म की बात होगी।

दूसरी तरफ विजुअल स्टूडियो (2012 नवंबर सीटीपी) इस बारे में शिकायत नहीं करता है। लेकिन इस समय प्रारंभकर्ता_सूची समर्थन बहुत अच्छा नहीं है, इसलिए यह एक बग हो सकता है।

उत्तर

10

यह LWG 2132 है जो अभी तक एक दोष रिपोर्ट नहीं है लेकिन इसे ठीक करने के लिए स्पष्ट सर्वसम्मति (और कार्यान्वयन अनुभव) है। मानक कहता है कि std::function का कन्स्ट्रक्टर किसी भी प्रकार को स्वीकार करेगा, इसलिए यदि प्रारंभिक है तो प्रारंभकर्ता-सूची निर्माता को अन्य रचनाकारों को हमेशा पसंद किया जाता है, तो आपका कोड std::initializer_list<std::function<void()>> से ऑब्जेक्ट a से प्रारंभ किए गए एक तत्व के साथ वेक्टर बनाने का प्रयास करता है। उसके बाद त्रुटि उत्पन्न होती है क्योंकि यद्यपि आप a से std::function<void()> बना सकते हैं जिसके परिणामस्वरूप ऑब्जेक्ट कॉल करने योग्य नहीं है।

दूसरे शब्दों में यह मुद्दा यह है कि std::function में एक अनजान टेम्पलेट कन्स्ट्रक्टर है जो किसी भी प्रकार से रूपांतरण की इजाजत देता है। इससे आपके मामले में समस्या आती है क्योंकि शुरुआती-सूची कन्स्ट्रक्टर अन्य कन्स्ट्रक्टरों को व्यवहार्य मानते हैं, और अवांछित function कन्स्ट्रक्टर का मतलब है कि किसी भी प्रकार से initializer_list<function<void()>> बनाना हमेशा प्रारंभ करना है ताकि प्रारंभकर्ता-सूची निर्माता हमेशा व्यवहार्य हो।

2132 के लिए प्रस्तावित संकल्प एक गैर-कॉल करने योग्य प्रकार से std::function बनाने से रोकता है, इसलिए प्रारंभकर्ता-सूची निर्माता व्यवहार्य नहीं है और vector कॉपी कन्स्ट्रक्टर को इसके बजाय बुलाया जाता है। I implemented that resolution for GCC 4.8, और यह पहले से ही क्लैंग की libC++ लाइब्रेरी में भी कार्यान्वित किया गया है।

+0

उत्तर के लिए धन्यवाद। एलडब्लूजी 2132 लिंक वास्तव में ऐसी समस्या के बारे में बात करता है जो समान लेकिन अलग है, इस मुद्दे को ठीक करने के लिए ऐसा ही होता है। मतलब यह समस्या केवल std :: फ़ंक्शन के लिए तय की जाएगी, न कि टेम्पलेट कन्स्ट्रक्टर वाले अन्य प्रकारों के लिए। मुझे लगता है कि वर्दी प्रारंभिकता के लिए मेरा नया नियम "जहां भी आप कर सकते हैं इसका उपयोग करें, सिवाय इसके कि ऑब्जेक्ट में प्रारंभकर्ता_सूची कन्स्ट्रक्टर है। फिर केवल उस निर्माता का उपयोग करें यदि आप उस कन्स्ट्रक्टर को चाहते हैं।"जिसका अर्थ यह भी है कि आप इसे टेम्पलेट कोड में उपयोग नहीं कर सकते हैं। –

+0

मैं नियम पसंद करता हूं" अनियंत्रित कन्स्ट्रक्टर टेम्पलेट्स न लिखें जो किसी भी प्रकार से निहित रूपांतरण की अनुमति देते हैं। "यदि आप इस तरह के प्रकार नहीं बनाते हैं तो आप ' उन लोगों के लिए समस्याएं पैदा नहीं करती हैं जो आपके प्रकार का उपयोग उन वर्गों के साथ करने का प्रयास करते हैं जिनके पास प्रारंभकर्ता-सूची निर्माता हैं। मानक लाइब्रेरी उस नियम का पालन नहीं करती है, लेकिन यह 'std :: function' के लिए तय की जा रही है। –

5

मुझे कोई कारण नहीं दिख रहा है कि इसे संकलित क्यों नहीं किया जाना चाहिए और दोनों जीसीसी (संस्करण 4.8.0 20121111) और क्लैंग (संस्करण 3.3 (ट्रंक 171007)) कोड संकलित करें। उस ने कहा, "वर्दी प्रारंभिक" वर्दी से बहुत दूर है: निश्चित रूप से ऐसे मामले हैं जहां आप एक कन्स्ट्रक्टर का आह्वान करते समय ब्रेसिज़ का उपयोग नहीं कर सकते हैं।

+0

जी ++ 4.7.2 ('4.7.2-5ubuntu1') कोड संकलित नहीं करता है। बहुत अजीब कंपाइलर त्रुटि संदेश: http://pastebin.com/b1mcbYRq – leemes

+1

@leemes प्रश्न के साथ खुलता है "निम्नलिखित कोड जीसीसी 4.7.2 या क्लैंग 3.2 में संकलित नहीं है:", मुझे लगता है कि ओपी यह जानता है (और शायद पहले स्थान पर सवाल का कारण है)। – WhozCraig

+0

@WozozCraig हाँ, लेकिन उन्होंने संकलक संदेश प्रदान नहीं किया। यही कारण है कि मैंने इस टिप्पणी को पहली जगह पोस्ट किया। – leemes

संबंधित मुद्दे