2017-10-03 10 views
6

इस कोड पर विचार करें:क्या मैं std :: संस्करण में प्रत्येक स्ट्रक्चर के लिए स्पष्ट रूप से एक कन्स्ट्रक्टर लिखने से बच सकता हूं?

#include <variant> 

struct x { 
    int y; 
}; 

int main() { 
    std::variant<x> v(std::in_place_type<x>, {3}); /*1*/ 
    return std::get<x>(v).y; 
} 

यह संकलन नहीं करता है और न करता जब लाइन /*1*/ से {} को दूर करने, भले ही कुल प्रारंभ

x a{3}; 
x b({3}); 

दोनों "निर्माता की तरह" रूपों में काम करता है। क्या मैं किसी भी तरह से std::variant प्रारंभकर्ता को अपने वास्तविक दुनिया के मामले में इस्तेमाल होने वाली प्रत्येक संरचना के लिए उबाऊ बॉयलरप्लेट कन्स्ट्रक्टर लिखने के बिना कुल प्रारंभिकरण का उपयोग करके structs बनाने की संभावना से अवगत करा सकता हूं?

मैं इस काम करने के लिए, किसी भी तरह, के रूप में cppreference प्रति दो भार के (5) और (6) प्रश्न में दोनों का कहना है कि

Constructs निर्दिष्ट विकल्प टी और साथ एक संस्करण initializes उम्मीद करेंगे तर्क साथ निहित मूल्य [...]

मैं जीसीसी 7 का उपयोग कर रहा है कि अगर मायने रखती है।

+0

यदि यह आपको शान्ति देता है, तो 'std :: make_unique' और परिवार की समान सीमा होती है :( – Rakete1111

+0

कुल प्रारंभिकरण हमेशा सी ++ प्रारंभिक प्रणाली –

उत्तर

1

कन्स्ट्रक्टर जोड़ने के अलावा इसके लिए कोई कामकाज नहीं है। दोनों भार के आप का उल्लेख, [variant.ctor]19 और [variant.ctor]23 क्रमशः के लिए मानक जनादेश इस:

प्रभाव: निहित मूल्य के रूप में अगर तर्क std​::​forward<Args>(args)... साथ प्रकार T का एक उद्देश्य डायरेक्ट-गैर सूची-आरंभ आरंभीकृत।

प्रभाव: निहित मूल्य के रूप में अगर तर्क il, std​::​forward<Args>(args)... साथ प्रकार T का एक उद्देश्य डायरेक्ट-गैर सूची-आरंभ आरंभीकृत।

तुम हमेशा कॉपी या का उपयोग कर वस्तु को स्थानांतरित कर सकते हैं:

std::variant<x> v(std::in_place_type<x>, x{3}); 
// or more clear and does the same thing 
std::variant<x> v(x{3}); 
3

शायद यह वही नहीं है जो आप पूछ रहे हैं, लेकिन प्रकार अनुमान पर भरोसा करने के बजाय वस्तु का स्पष्ट रूप से निर्माण करने के बारे में क्या है?

#include <variant> 

struct x { 
    int y; 
}; 

int main() { 
    std::variant<x> v(std::in_place_type<x>, x{3}); 
    return std::get<x>(v).y; 
} 
+0

में कांटा रहा है वास्तव में मैं इससे खुश हूं!मेरा प्रश्न, प्रति शीर्षक, कन्स्ट्रक्टर से बचने के बारे में है, जो यह प्राप्त करता है। यह तकनीकी रूप से कुछ घूमने में शामिल होगा लेकिन साधारण मामलों में ऑप्टिमाइज़र इसका ओवरहेड नहीं रखेगा। –

+0

वास्तव में यह स्पष्ट होगा यदि आपकी कक्षा एक चलती कन्स्ट्रक्टर प्रदान करती है। जैसा कि आप किसी स्पष्ट रूप से परिभाषित कन्स्ट्रक्टर नहीं चाहते हैं, आपको निहित चलने वाले कन्स्ट्रक्टर (या कम से कम एक को डिफ़ॉल्ट करना) की गारंटी देनी चाहिए। – cbuchart

0

आप overkill जाना चाहते हैं, हम एक कारखाने प्रकार एक रूपांतरण ऑपरेटर है कि बना सकते हैं:

template <class... Args> 
struct list_init_from { 
    std::tuple<Args...> args; 

    template <class T> 
    operator T() { 
     return std::apply([](auto... args){ 
      return T{args...}; 
     }, args); 
    } 
}; 

template <class... Args> 
list_init_from(Args...) -> list_init_from<Args...>; 

कौन सा आप इसका उपयोग कर सकते हैं:

std::variant<x> v(std::in_place_type<x>, list_init_from{3}); 

यह काम करता है, लेकिन म्यू छोड़ देता है वां वांछित होने के लिए: रूपांतरण अग्रेषण पर पूर्ण अग्रेषण, SFINAE, और स्पष्ट रूप से निर्दिष्ट करने के लिए कि किस प्रकार के रूपांतरणों को पाठकों को अभ्यास करने की अनुमति दी जाती है।

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

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