2016-05-11 28 views
5

Should I use() or {} when forwarding arguments? देखें। foo एक std::vector क्लोन है।std :: make_unique et al के लिए std :: startizer_list ओवरलोड मौजूद क्यों नहीं हैं?

N4140 में, unique.ptr.createstd::make_unique इतनी के रूप में निर्दिष्ट किया जाता है:

template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);

  • टिप्पणियां: इस समारोह अधिभार संकल्प में भाग नहीं होगा जब तक कि T एक सरणी नहीं है।

  • पर लौटें: unique_ptr<T>(new T(std::forward<Args>(args)...))

कार्यान्वयन इसका मतलब है कि () बजाय {} उपयोग करने के लिए वस्तुओं प्रारंभ करने की आवश्यकता है। उदाहरण के लिए,

auto s1 = std::make_unique<foo>(3, 1).get()->size(); 
auto s2 = std::make_unique<foo>(1).get()->size(); 
auto s3 = std::make_unique<foo>(2).get()->size(); 
std::cout << s1 << s2 << s3; 

आउटपुट 312 उत्पादन जबकि अगर {} (std::make_unique अंदर) इस्तेमाल किया गया था 211 होगा निम्नलिखित। चूंकि प्रारंभिक सूची को घटाया नहीं जा सकता है, इसलिए बाद के परिणाम प्राप्त करने के लिए std::initializer_list स्पष्ट रूप से पारित किया जाना चाहिए। सवाल यह है कि, इस तरह एक अधिभार क्यों नहीं है?

namespace test 
{ 

template <class T, class Deduce> 
std::unique_ptr<T> make_unique(std::initializer_list<Deduce> li) 
{ 
    return ::std::make_unique<T>(li); 
} 

}; 

int main() 
{ 
    auto p1 = test::make_unique<foo>({3, 1}).get()->size(); 
    auto p2 = test::make_unique<foo>({1}).get()->size(); 
    auto p3 = test::make_unique<foo>({2}).get()->size(); 
    std::cout << p1 << p2 << p3; 
} 

आउटपुट 211

मैं बहुत अच्छे कारण होने के कारण "आप इसे स्वयं लिख सकते हैं" या "मानक को फलने से रोकने के लिए" कारणों पर विचार नहीं करते हैं। क्या इस अधिभार को प्रदान करने के लिए कोई नुकसान है?

उत्तर

2

मुझे पूरा इतिहास नहीं पता है, लेकिन सबसे अधिक संभावना है कि "कोई भी इसका प्रस्ताव नहीं है"।

इस के लिए साक्ष्य इस तथ्य से समर्थित है कि std::make_unique केवल सी ++ 14 में जोड़ा गया था, फिर भी std::unique_ptr सी ++ 11 में मौजूद था।

कोड और std::make_shared के लिए प्रस्तावों (जो अंततः make_unique में नजर आता था) (बढ़ावा में) initializer_list और initialisation वाक्य रचना से इसका समर्थन करने से पहले ही अस्तित्व में।

एक चीज जो आप कर सकते हैं, इसे प्रस्तावित करना है (और अगर कोई है तो कोने के मामलों को बाहर करें, उदाहरण के लिए अगर लोड प्रकार initializer_list का समर्थन नहीं करता है तो ओवरलोड को हटाने के लिए SFINAE का उपयोग करें)।

+0

मुझे नहीं लगता कि SFINAE आवश्यक है है। 'make_unique > (1, 73); 'अगर मैं इसे नामस्थान से बाहर ले जाता हूं और नामस्थान स्टेड का उपयोग कर रहा हूं, तो' पूरी तरह से ठीक काम करता है '(यह सुनिश्चित करने के लिए कि दोनों अधिभार दिखाई दे रहे हैं)। अगर कोई 'make_unique > ({1, 73}) करता है;' यह उनकी गलती है। – user6319825

+0

@ user6319825।हां, एसएफआईएनएई आवश्यक नहीं है, संकलन किसी भी तरह से विफल रहता है, बस मेरे अनुभव में एक SFINAE पर्यावरण में त्रुटि संदेश निदान करने के लिए "आसान" हैं। – Niall

+0

फिर भी। उन्होंने जानबूझकर कहा कि 'नया टी (std :: आगे (तर्क) ...)' इसे वैकल्पिक रूप से [वैकल्पिक] (http://eel.is/c++draft/optional.object) के कार्यान्वयन के लिए छोड़ने के बजाय .ctor # 23): "निहित मूल्य को आरंभ करता है जैसे डायरेक्ट-गैर-सूची- तर्क 'टी'' के ऑब्जेक्ट को प्रारंभ करने के लिए 'st' :: आगे (तर्क)' ...." इससे मुझे लगता है कि वहां है विशेष रूप से 'make_unique' के लिए कुछ चर्चा * कहीं *। – user6319825

0

मुझे लगता है कि यह सिर्फ एक टेम्पलेट कटौती मुद्दा है, this answer देखें।

आप इन की कोशिश कर सकते:

int main() 
{ 
    auto p1 = std::make_unique<foo>(std::initializer_list<int>{3, 1}).get()->size(); 
    auto p2 = std::make_unique<foo>(foo{1}).get()->size(); 
    auto l3 = {2}; 
    auto p3 = std::make_unique<foo>(l3).get()->size(); 
    std::cout << p1 << p2 << p3; 
} 
संबंधित मुद्दे