दिलचस्प पोस्ट
पायथन में लगभग समानता के लिए फ्लोट की तुलना करने का सबसे अच्छा तरीका क्या है? शीर्ष स्तर की विंडो को पुनर्निर्देशित करने से IFRAME को कैसे रोकें एंड्रॉइड एमुलेटर पर कोई इंटरनेट नहीं – क्यों और कैसे ठीक करें? जीआईटी के इतिहास में बड़ी फाइलें कैसे ढूंढें / पहचानें? IOS7 में स्थिति बार और नेविगेशन बार समस्या एक संशोधित प्रीर्डर ट्री ट्रवर्सल मॉडल (नेस्टेड सेट) को एक <ul> में लेना सीएसएस ट्रांसफ़ॉर्म, क्रोम में दांतेदार किनारों मॉड्यूलस डिविजन काम कैसे करता है बाश के मूल्यों के जोड़े से अधिक लूपिंग Printf के% s विनिर्देशक के साथ छपाई के व्यवहार का क्या व्यवहार है? उपयोगकर्ता से हस्ताक्षर का उपयोग करते हुए किसी सर्वर दस्तावेज़ पर पीडीएफ़ पर हस्ताक्षर करना Laravel 5 – URL से सार्वजनिक निकालें पायथन में सूचियों की तुलना में ट्यूपल्स अधिक कुशल हैं? पायथन में "आंतरिक अपवाद" (ट्रैसबैक के साथ)? प्राइमफॉसेस इनपुट कंप्यूटर्स के माध्यम से प्राप्त यूनिकोड इनपुट दूषित हो गए हैं

मैं केवल कैसे संरक्षित या निजी कंस्ट्रक्टर के साथ एक क्लास पर :: std :: make_shared कॉल करूं?

मेरे पास यह कोड है जो काम नहीं करता है, लेकिन मुझे लगता है कि इरादा स्पष्ट है:

testmakeshared.cpp

#include <memory> class A { public: static ::std::shared_ptr<A> create() { return ::std::make_shared<A>(); } protected: A() {} A(const A &) = delete; const A &operator =(const A &) = delete; }; ::std::shared_ptr<A> foo() { return A::create(); } 

लेकिन मुझे यह त्रुटि मिलती है जब मैं इसे संकलित करता हूं:

 g++ -std=c++0x -march=native -mtune=native -O3 -Wall testmakeshared.cpp In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:52:0, from /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/memory:86, from testmakeshared.cpp:1: testmakeshared.cpp: In constructor 'std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc) [with _Tp = A, _Alloc = std::allocator<A>, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]': /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:518:8: instantiated from 'std::__shared_count<_Lp>::__shared_count(std::_Sp_make_shared_tag, _Tp*, const _Alloc&, _Args&& ...) [with _Tp = A, _Alloc = std::allocator<A>, _Args = {}, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]' /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:986:35: instantiated from 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<A>, _Args = {}, _Tp = A, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]' /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:313:64: instantiated from 'std::shared_ptr<_Tp>::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<A>, _Args = {}, _Tp = A]' /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:531:39: instantiated from 'std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = A, _Alloc = std::allocator<A>, _Args = {}]' /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:547:42: instantiated from 'std::shared_ptr<_Tp1> std::make_shared(_Args&& ...) [with _Tp = A, _Args = {}]' testmakeshared.cpp:6:40: instantiated from here testmakeshared.cpp:10:8: error: 'A::A()' is protected /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:400:2: error: within this context Compilation exited abnormally with code 1 at Tue Nov 15 07:32:58 

यह संदेश मूल रूप से यह कह रहा है कि टेम्पलेट ::std::make_shared स्टैक में कुछ यादृच्छिक पद्धति जिस तरह से नीचे हैं ::std::make_shared तक पहुंच नहीं सकती क्योंकि यह संरक्षित है।

लेकिन मैं वास्तव में दोनों ::std::make_shared का उपयोग करना चाहता ::std::make_shared और इस क्लास के ऑब्जेक्ट को बनाने से किसी को रोकने से रोकता ::std::make_shared जो कि ::std::shared_ptr क्या इसे पूरा करने का कोई रास्ता है?

वेब के समाधान से एकत्रित समाधान "मैं केवल कैसे संरक्षित या निजी कंस्ट्रक्टर के साथ एक क्लास पर :: std :: make_shared कॉल करूं?"

यह जवाब शायद बेहतर है, और जो मैं स्वीकार करता हूँ लेकिन मैं भी एक विधि के साथ आया है जो कुटिलतापूर्ण है, लेकिन अभी भी सब कुछ अभी भी इनलाइन बनाते हैं और उसे व्युत्पन्न वर्ग की आवश्यकता नहीं होती है:

 #include <memory> #include <string> class A { protected: struct this_is_private; public: explicit A(const this_is_private &) {} A(const this_is_private &, ::std::string, int) {} template <typename... T> static ::std::shared_ptr<A> create(T &&...args) { return ::std::make_shared<A>(this_is_private{0}, ::std::forward<T>(args)...); } protected: struct this_is_private { explicit this_is_private(int) {} }; A(const A &) = delete; const A &operator =(const A &) = delete; }; ::std::shared_ptr<A> foo() { return A::create(); } ::std::shared_ptr<A> bar() { return A::create("George", 5); } ::std::shared_ptr<A> errors() { ::std::shared_ptr<A> retval; // Each of these assignments to retval properly generates errors. retval = A::create("George"); retval = new A(A::this_is_private{0}); return ::std::move(retval); } 

2017-01-06 को संपादित करें: मैंने इसे स्पष्ट करने के लिए इसे स्पष्ट करने के लिए कहा कि यह विचार कंसल्टर्स के लिए स्पष्ट और सरल है क्योंकि तर्क तर्क देते हैं क्योंकि अन्य लोग उन पंक्तियों के साथ उत्तर प्रदान कर रहे थे और इसके बारे में उलझन में लग रहा था।

के लिए आवश्यकताओं को देखते हुए std::make_shared में 20.7.2.2.6 shared_ptr creation [util.smartptr.shared.create], पैरा 1:

आवश्यक है: अभिव्यक्ति ::new (pv) T(std::forward<Args>(args)...) , जहां pv का टाइप void* और T ऑब्जेक्ट को पकड़ने के लिए उपयुक्त भंडार को इंगित करता है, यह अच्छी तरह से बनाई जाएगी । A आवंटक (17.6.3.5) होगा। प्रतिलिपि कन्स्ट्रस्ट्रक्टर और A डिस्ट्रक्टर अपवाद नहीं फेंकेंगे।

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

एक सरल समाधान ए से प्राप्त करना है इसके लिए A को इंटरफ़ेस या पॉलीमोर्फ़िक प्रकार भी बनाने की आवश्यकता नहीं है।

 // interface in header std::shared_ptr<A> make_a(); // implementation in source namespace { struct concrete_A: public A {}; } // namespace std::shared_ptr<A> make_a() { return std::make_shared<concrete_A>(); } 

संभवत: सरल समाधान मोहित आरोन के पिछले उत्तर के आधार पर और डीएलएफ के सुझाव को शामिल करना।

 #include <memory> class A { public: static std::shared_ptr<A> create() { struct make_shared_enabler : public A {}; return std::make_shared<make_shared_enabler>(); } private: A() {} }; 

इसके लिए एक साफ समाधान यहां दिया गया है:

 #include <memory> class A { public: static shared_ptr<A> Create(); private: A() {} struct MakeSharedEnabler; }; struct A::MakeSharedEnabler : public A { MakeSharedEnabler() : A() { } }; shared_ptr<A> A::Create() { return make_shared<MakeSharedEnabler>(); } 

चूंकि मुझे पहले से प्रदान किए गए उत्तर पसंद नहीं था I ने खोज करने का निर्णय लिया और मुझे एक ऐसा समाधान मिला जो पहले के उत्तर के रूप में सामान्य नहीं है, लेकिन मैं इसे बेहतर (टीएम) पसंद करता हूं। पिछली पीढ़ी में यह ओमनिफिरा द्वारा प्रदान की गई तुलना में बहुत अच्छा नहीं है, लेकिन अन्य लोग भी इसे पसंद कर सकते हैं 🙂

यह मेरे द्वारा आविष्कार नहीं है, लेकिन यह जोनाथन वक्ली (जीसीसी डेवलपर) का विचार है

दुर्भाग्य से यह सभी कंपाइलरों के साथ काम नहीं करता क्योंकि यह std :: allocation_shared कार्यान्वयन में एक छोटा परिवर्तन पर निर्भर करता है। लेकिन यह परिवर्तन अब मानक पुस्तकालयों के लिए एक प्रस्तावित अद्यतन है, इसलिए यह भविष्य में सभी कंपलर्स द्वारा समर्थित हो सकता है। यह जीसीसी 4.7 पर काम करता है।

सी ++ लाइब्रेरी वर्किंग ग्रुप परिवर्तन अनुरोध यहां है: http://lwg.github.com/issues/lwg-active.html#2070

उदाहरण उपयोग के साथ जीसीसी पैच यहां है: http://old.nabble.com/Re%3A–v3–implement-pointer_traits-and-allocator_traits-p31723738.html

समाधान कस्टम आबंटक के साथ std :: allocate_shared (std :: make_shared के बजाय) का प्रयोग करने के विचार पर काम करता है जिसे निजी निर्माता के साथ क्लास में मित्र घोषित किया जाता है।

ओपी से उदाहरण इस तरह दिखेगा:

 #include <memory> template<typename Private> struct MyAlloc : std::allocator<Private> { void construct(void* p) { ::new(p) Private(); } }; class A { public: static ::std::shared_ptr<A> create() { return ::std::allocate_shared<A>(MyAlloc<A>()); } protected: A() {} A(const A &) = delete; const A &operator =(const A &) = delete; friend struct MyAlloc<A>; }; int main() { auto p = A::create(); return 0; } 

एक अधिक जटिल उदाहरण जो कि उपयोगिता पर आधारित है। इसके साथ मैं ल्यूक के समाधान का उपयोग नहीं कर सका। लेकिन ओम्नीफायस द्वारा एक को अनुकूलित किया जा सकता है। ऐसा नहीं है कि पिछले उदाहरण में सभी लोग इस में MyAlloc का उपयोग कर एक ए ऑब्जेक्ट बना सकते हैं, इसके अलावा A या B को बनाने के अलावा कोई तरीका नहीं है () विधि

 #include <memory> template<typename T> class safe_enable_shared_from_this : public std::enable_shared_from_this<T> { public: template<typename... _Args> static ::std::shared_ptr<T> create(_Args&&... p_args) { return ::std::allocate_shared<T>(Alloc(), std::forward<_Args>(p_args)...); } protected: struct Alloc : std::allocator<T> { template<typename _Up, typename... _Args> void construct(_Up* __p, _Args&&... __args) { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } }; safe_enable_shared_from_this(const safe_enable_shared_from_this&) = delete; safe_enable_shared_from_this& operator=(const safe_enable_shared_from_this&) = delete; }; class A : public safe_enable_shared_from_this<A> { private: A() {} friend struct safe_enable_shared_from_this<A>::Alloc; }; class B : public safe_enable_shared_from_this<B> { private: B(int v) {} friend struct safe_enable_shared_from_this<B>::Alloc; }; int main() { auto a = A::create(); auto b = B::create(5); return 0; } 
 struct A { public: template<typename ...Arg> std::shared_ptr<A> static create(Arg&&...arg) { struct EnableMakeShared : public A { EnableMakeShared(Arg&&...arg) :A(std::forward<Arg>(arg)...) {} }; return std::make_shared<EnableMakeShared>(std::forward<Arg>(arg)...); } void dump() const { std::cout << a_ << std::endl; } private: A(int a) : a_(a) {} A(int i, int j) : a_(i + j) {} A(std::string const& a) : a_(a.size()) {} int a_; }; 

इस बारे में कैसा है?

 static std::shared_ptr<A> create() { std::shared_ptr<A> pA(new A()); return pA; } 

यदि आप एक आचरण लेना चाहते हैं, तो यह थोड़ा मदद कर सकता है।

 #include <memory> #include <utility> template<typename S> struct enable_make : public S { template<typename... T> enable_make(T&&... t) : S(std::forward<T>(t)...) { } }; class foo { public: static std::unique_ptr<foo> create(std::unique_ptr<int> u, char const* s) { return std::make_unique<enable_make<foo>>(std::move(u), s); } protected: foo(std::unique_ptr<int> u, char const* s) { } }; void test() { auto fp = foo::create(std::make_unique<int>(3), "asdf"); } 

आपके पास दो सख्ती से संबंधित क्लास ए और बी हैं, जो एक साथ काम करते हैं, तब ऐसा अधिक बालों और दिलचस्प समस्या होती है।

कहो एक "मास्टर क्लास" है और बी इसके "गुलाम" यदि आप केवल बी के लिए तत्काल ब्याज देना चाहते हैं, तो आप बी के कन्स्ट्रक्टर को निजी बना सकते हैं, और दोस्त बी से ए को इस तरह से बना सकते हैं

 class B { public: // B your methods... private: B(); friend class A; }; 

दुर्भाग्य से A एक विधि से std::make_shared<B>() को कॉल करने से कम्पाइलर B::B() निजी होने के बारे में शिकायत करेगा।

इसके लिए मेरा समाधान सार्वजनिक Pass डमी वर्ग (जैसे nullptr_t ) को B अंदर बनाना है जो कि निजी निर्माता है और A साथ दोस्त है और B के निर्माता को सार्वजनिक करता है और इसके तर्कों को Pass करें जैसे कि यह।

 class B { public: class Pass { Pass() {} friend class A; }; B(Pass, int someArgument) { } }; class A { public: A() { // This is valid auto ptr = std::make_shared<B>(B::Pass(), 42); } }; class C { public: C() { // This is not auto ptr = std::make_shared<B>(B::Pass(), 42); } }; 

मुझे पता है कि यह धागा बहुत पुराना है, लेकिन मुझे ऐसे जवाब मिल गए हैं जिसके लिए कंस्ट्रक्टर को विरासत या अतिरिक्त तर्क की आवश्यकता नहीं है जिसे मैं कहीं और नहीं देख सकता था। यह पोर्टेबल नहीं है:

 #include <memory> #if defined(__cplusplus) && __cplusplus >= 201103L #define ALLOW_MAKE_SHARED(x) friend void __gnu_cxx::new_allocator<test>::construct<test>(test*); #elif defined(_WIN32) || defined(WIN32) #if defined(_MSC_VER) && _MSC_VER >= 1800 #define ALLOW_MAKE_SHARED(x) friend class std::_Ref_count_obj; #else #error msc version does not suport c++11 #endif #else #error implement for platform #endif class test { test() {} ALLOW_MAKE_SHARED(test); public: static std::shared_ptr<test> create() { return std::make_shared<test>(); } }; int main() { std::shared_ptr<test> t(test::create()); } 

मैंने विंडोज़ और लिनक्स पर परीक्षण किया है, इसके लिए अलग-अलग प्लेटफार्मों के लिए टिविकिंग की आवश्यकता हो सकती है।

मैं इस तरह के टेम्पलेट के साथ आया हूं जो संरक्षित संरक्षकों की समस्या को काफी अच्छी तरह से निकालता है:

 // helper template not used directly in code: template<typename T> struct CHelpExposeProtectedConstructor : public T { template<typename...Args> CHelpExposeProtectedConstructor(Args...args) : T(std::forward<Args>(args)...) {} }; /** * this uses std::make_shared on classes which have protected constructors */ template<typename T, typename...Args> auto MakeSharedFromProtected(Args...args) -> std::shared_ptr<T> { return std::make_shared<CHelpExposeProtectedConstructor<T>>(std::forward<Args>(args)...); } 

सिर्फ MakeSharedFromProtected बजाय make_shared MakeSharedFromProtected उपयोग करें और समस्या हल।

दुर्भाग्य से यह निजी कन्स्ट्रक्टर के मामले में मदद नहीं करता है।

 #include <iostream> #include <memory> class A : public std::enable_shared_from_this<A> { private: A(){} explicit A(int a):m_a(a){} public: template <typename... Args> static std::shared_ptr<A> create(Args &&... args) { class make_shared_enabler : public A { public: make_shared_enabler(Args &&... args):A(std::forward<Args>(args)...){} }; return std::make_shared<make_shared_enabler>(std::forward<Args>(args)...); } int val() const { return m_a; } private: int m_a=0; }; int main(int, char **) { std::shared_ptr<A> a0=A::create(); std::shared_ptr<A> a1=A::create(10); std::cout << a0->val() << " " << a1->val() << std::endl; return 0; } 

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

 class CVal { friend std::shared_ptr<CVal>; friend std::_Ref_count<CVal>; public: static shared_ptr<CVal> create() { shared_ptr<CVal> ret_sCVal(new CVal()); return ret_sCVal; } protected: CVal() {}; ~CVal() {}; };