2017-12-17 84 views
5

मान लीजिए कि हम एक उपयोगकर्ता-निर्धारित कटौती गाइड के साथ इस तरह एक वर्ग करते हैं: Foo foo { 10 };:उपयोगकर्ता-परिभाषित बनाम स्वचालित टेम्पलेट कटौती गाइड प्राथमिकताओं

template<typename T, typename... Args> 
struct Foo 
{ 
    Foo(Args&&...) { std::cout << "just Args: " << __PRETTY_FUNCTION__ << std::endl; } 
    Foo(Args&&..., T&&) { std::cout << "Args and T: " << __PRETTY_FUNCTION__ << std::endl; } 
}; 

template<typename... Args> 
Foo(Args&&...) -> Foo<Void, Args...>; 

अब इस वर्ग का एक उदाहरण बनाने के लिए कोशिश करते हैं। अनुमानित टेम्पलेट तर्क क्या होगा और किस कन्स्ट्रक्टर को बुलाया जाएगा?

कुछ प्रयोगों के बाद यह संकलक पर निर्भर करता है। अर्थात्, जीसीसी 7 और बजना 6 (ट्रंक से), स्वत: मार्गदर्शिका चुनने के लिए, एक खाली पैक के साथ int साथ T और Args instantiating लगते हैं इसलिए उत्पादन

Args and T: Foo<T, Args>::Foo(Args&& ..., T&&) [with T = int; Args = {}] 

बजना 5, दूसरे हाथ पर, चुनता है उपयोगकर्ता द्वारा परिभाषित मार्गदर्शिका:

just Args: Foo<Void, int>::Foo(Args &&...) [T = Void, Args = <int>] 

कौन सा विकल्प सही है, और इस मामले में उपयोगकर्ता द्वारा परिभाषित कटौती मार्गदर्शिका का उपयोग कैसे किया जा सकता है?

पूर्ण उदाहरण wandbox पर उपलब्ध है।

उत्तर

3

चलिए पहले सिद्धांतों से चले जाते हैं। Foo{10} से अनुमान की कोशिश इस सेट पर अधिभार संकल्प कर शामिल है:

template <typename T, typename... Args> 
Foo<T, Args...> __f(Args&&...); // ctor #1 

template <typename T, typename... Args> 
Foo<T, Args...> __f(Args&&..., T&&); // ctor #2 

template <typename... Args> 
Foo<Void, Args...> __f(Args&&...); // deduction guide 

समारोह पहले निर्माता से संश्लेषित में, T एक गैर निष्कर्ष निकाला संदर्भ है। दूसरे कन्स्ट्रक्टर से संश्लेषित समारोह में, Args एक गैर-कटौती संदर्भ है। तो न तो व्यवहार्य हैं। कटौती मार्गदर्शिका व्यवहार्य है, इसलिए यह सबसे अच्छा व्यवहार्य उम्मीदवार है, इसलिए हम Foo<Void, int> के साथ समाप्त होते हैं।

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

कोई अन्य व्यवहार एक कंपाइलर बग है (दायर 83447)।

+1

सीआरओआर # 2 से संश्लेषित समारोह में 'Args' एक गैर-कटौती संदर्भ क्यों है? ऐसा लगता है कि यह पूरी तरह से deducible है: इस विशेष मामले में एक खाली पैक। – 0xd34df00d

+1

@ 0xd34f00d http://eel.is/c++draft/temp#deduct.type-5.7 – Barry

+0

ठीक है, मैंने एक साधारण उदाहरण फेंक दिया है जो आपने बग्रेपोर्ट में जो दिखाया है उसके करीब है, और यह ठीक संकलित है सभी जीसीसी के साथ मैंने कोशिश की और दोनों क्लैंग 5 और 6, इसलिए मैंने माना कि यह सही है। आपके द्वारा दिया गया लिंक साबित करता है कि यह नहीं है! दिलचस्प बात यह है कि क्लैंग <4 कोड को खारिज कर देता है। अभी तक, कोड को मौजूदा कंपाइलर्स के साथ काम करने के लिए, मैंने दूसरे सीटीआर में एक डमी टैग पैरामीटर जोड़ा है, क्योंकि सीटीओ एक कार्यान्वयन विस्तार है और क्लास उपयोगकर्ताओं द्वारा नहीं कहा जाना चाहिए। आपका बहुत बहुत धन्यवाद! – 0xd34df00d

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