How to make boost::make_shared a friend of my class?

You don't need to template the friend part, but you need to signify that the friend function is a template: friend boost::shared_ptr boost::make_shared(/* ... */) That works with Comeau and current GCC versions but fails with VC. Better would be the following form: friend boost::shared_ptr boost::make_shared(/* ... */) That works across multiple compilers now - I tested it on VC8, VC10, GCC 4.2, GCC 4.5 and Comeau 4.3 Alternatively using a qualified name to refer to a particular instance of the function template as Martin does should work and does with Comeau, but GCC chokes on it A useful alternative that doesn't depend on the implementation details of make_shared() (and thus also works with VC10s TR1 implementation ) is to use the pass-key-idiom for access-protection of the constructor and to befriend the create() function instead, e.g. : class Connection { // ... public: class Key { friend boost::shared_ptr create(const ConnectionManagerPtr&, const std::string&); Key() {} }; Connection(const ConnectionManagerPtr&, const std::string&, const Key&); }; boost::shared_ptr create(const ConnectionManagerPtr& p, const std::string& s) { return boost::make_shared(p, s, Connection::Key()); }.

You don't need to template the friend part, but you need to signify that the friend function is a template: friend boost::shared_ptr boost::make_shared(/* ... */); // ^^ That works with Comeau and current GCC versions but fails with VC. Better would be the following form: friend boost::shared_ptr boost::make_shared(/* ... */); That works across multiple compilers now - I tested it on VC8, VC10, GCC 4.2, GCC 4.5 and Comeau 4.3. Alternatively using a qualified name to refer to a particular instance of the function template as Martin does should work and does with Comeau, but GCC chokes on it. A useful alternative that doesn't depend on the implementation details of make_shared() (and thus also works with VC10s TR1 implementation) is to use the pass-key-idiom for access-protection of the constructor and to befriend the create() function instead, e.g. : class Connection { // ... public: class Key { friend boost::shared_ptr create(const ConnectionManagerPtr&, const std::string&); Key() {} }; Connection(const ConnectionManagerPtr&, const std::string&, const Key&); }; boost::shared_ptr create(const ConnectionManagerPtr& p, const std::string& s) { return boost::make_shared(p, s, Connection::Key()); }.

I've just read Herb Sutter post on the subject and the outcome is that there is no portable solution to this problem. The code snippet you gave works on almost all compilers except GCC which I happen to develop on. So instead of using make_shared I reverted to using normal shared_ptr constructor.

– kyku Aug 1 '10 at 11:07 Could you please post a link to that post? – Basilevs Aug 1 '10 at 14:29 1 @kyk: What versions? I tested that on GCC... Note that Sutters article is 7 years old.

– Georg Fritzsche Aug 1 '10 at 23:41 @bas: This one from 2003 I guess. – Georg Fritzsche Aug 1 '10 at 23:44 Ok, the problem I was having was that I skipped constructor parameter type in friend declaration. So it shold be something like friend boost::shared_ptr boost::make_shared(const std::string&); – kyku Aug 1 '107 at 10:42.

I would try without the template part. After all, you want a specific instantiation of the (template) function to be a friend of your class, aren't you? Does friend boost::shared_ptr boost::make_shared(const ConnectionManagerPtr&, const std::string&); work?

If that's not the solution, it might be helpful to give us the compiler messages you're getting ...

Unless the specification boost::make_shared says this will work, it might work sometimes, then break when the implementation of boost::make_shared is changed. You cannot know. You should never declare friend some code that you don't control.

– curiousguy Oct 10 at 13:46 I cannot see how a future change in the implementation of boost::make_shared could break anything. After all declaring it as a friend has the same effect to make_shared as making all members of your class public, which is perfectly covered by the specification of make_shared. Afaik, friend will never change runtime behaviour it only influences the visibility at compile time.

I agree that this is probably not good style and should perhaps be avoided, but imo this is not a reason for a downvote :) (after all, the accepted answer proposes mainly the same solution...) – MartinStettner Oct 10 at 15:12 "After all declaring it as a friend has the same effect to make_shared as making all members of your class public" Absolutely not: it makes them accessible to the definition of boost::make_shared, and you don't know what the definition of boost::make_shared contains (and you shouldn't care). Anyway, if a specification says something must be public, than it must be public, end of story. – curiousguy Oct 10 at 15:38.

I think that is not the right place to use make_shared. Just construct your object with operator new and pass the pointer to shared_ptr constructor. That way you don't need to be friends with anyone.

BTW, why template arguments and function arguments are of different type?

1 As there is no portable solution to the problem I choose this answer as accepted. BTW make_shared is preffered for performance reasons, because it requires one memory allocation per shared_ptr and gives better cache locality. – kyku Aug 1 '10 at 11:09.

Below are some macros I wrote up to do this for you. In your case, you would use: BOOST_MAKE_SHARED_2ARG_CONSTRUCTOR(Connection, const ConnectionManagerPtr&, const std::string&); Macro definitions: // Required includes #include #include #include // Helper macro #define CONST_REFERENCE(T) boost::add_reference::type>::type /** BOOST_MAKE_SHARED_nARG_CONSTRUCTOR(CLASS_NAME, ARG1_TYPE, ARG2_TYPE, ...) * * Use this macro inside the body of a class to declare that boost::make_shared * should be considered a friend function when used in conjunction with the * constructor that takes the given argument types. This allows the constructor * to be declared private (making it impossible to accidentally create an instance * of the object without immediatly storing it in a boost::shared_ptr).

* Example usage: * * class Foo { * private: * Foo(int size, const char* name); * MAKE_SHARED_2ARG_CONSTRUCTOR(Foo, int, const char*); * }; * * boost::shared_ptr myFoo = boost::make_shared(3, "Bob"); * * Note that you need to explicitly specify the number of arguments * that the constructor takes as part of the macro name. Also, note that * macros don't mix well with templated types that contain commas -- so * if you have such a type, then you should typedef it to a shorter name * before using it with this macro. */ #define BOOST_MAKE_SHARED_0ARG_CONSTRUCTOR(CLASS_NAME) \ friend boost::shared_ptr boost::make_shared() #define BOOST_MAKE_SHARED_1ARG_CONSTRUCTOR(CLASS_NAME, ARG_TYPE1) \ friend boost::shared_ptr boost::make_shared(CONST_REFERENCE(ARG_TYPE1)) #define BOOST_MAKE_SHARED_2ARG_CONSTRUCTOR(CLASS_NAME, ARG_TYPE1, ARG_TYPE2) \ friend boost::shared_ptr boost::make_shared(CONST_REFERENCE(ARG_TYPE1), CONST_REFERENCE(ARG_TYPE2)) #define BOOST_MAKE_SHARED_3ARG_CONSTRUCTOR(CLASS_NAME, ARG_TYPE1, ARG_TYPE2, ARG_TYPE3) \ friend boost::shared_ptr boost::make_shared(CONST_REFERENCE(ARG_TYPE1), CONST_REFERENCE(ARG_TYPE2), CONST_REFERENCE(ARG_TYPE3)) #define BOOST_MAKE_SHARED_4ARG_CONSTRUCTOR(CLASS_NAME, ARG_TYPE1, ARG_TYPE2, ARG_TYPE3, ARG_TYPE4) \ friend boost::shared_ptr boost::make_shared(CONST_REFERENCE(ARG_TYPE1), CONST_REFERENCE(ARG_TYPE2), CONST_REFERENCE(ARG_TYPE3), CONST_REFERENCE(ARG_TYPE4)) #define BOOST_MAKE_SHARED_5ARG_CONSTRUCTOR(CLASS_NAME, ARG_TYPE1, ARG_TYPE2, ARG_TYPE3, ARG_TYPE4, ARG_TYPE5) \ friend boost::shared_ptr boost::make_shared(CONST_REFERENCE(ARG_TYPE1), CONST_REFERENCE(ARG_TYPE2), CONST_REFERENCE(ARG_TYPE3), CONST_REFERENCE(ARG_TYPE4), CONST_REFERENCE(ARG_TYPE5)) #define BOOST_MAKE_SHARED_6ARG_CONSTRUCTOR(CLASS_NAME, ARG_TYPE1, ARG_TYPE2, ARG_TYPE3, ARG_TYPE4, ARG_TYPE5, ARG_TYPE6) \ friend boost::shared_ptr boost::make_shared(CONST_REFERENCE(ARG_TYPE1), CONST_REFERENCE(ARG_TYPE2), CONST_REFERENCE(ARG_TYPE3), CONST_REFERENCE(ARG_TYPE4), CONST_REFERENCE(ARG_TYPE5), CONST_REFERENCE(ARG_TYPE6)) #define BOOST_MAKE_SHARED_7ARG_CONSTRUCTOR(CLASS_NAME, ARG_TYPE1, ARG_TYPE2, ARG_TYPE3, ARG_TYPE4, ARG_TYPE5, ARG_TYPE6, ARG_TYPE7) \ friend boost::shared_ptr boost::make_shared(CONST_REFERENCE(ARG_TYPE1), CONST_REFERENCE(ARG_TYPE2), CONST_REFERENCE(ARG_TYPE3), CONST_REFERENCE(ARG_TYPE4), CONST_REFERENCE(ARG_TYPE5), CONST_REFERENCE(ARG_TYPE6)), CONST_REFERENCE(ARG_TYPE7)) #define BOOST_MAKE_SHARED_8ARG_CONSTRUCTOR(CLASS_NAME, ARG_TYPE1, ARG_TYPE2, ARG_TYPE3, ARG_TYPE4, ARG_TYPE5, ARG_TYPE6, ARG_TYPE7, ARG_TYPE8) \ friend boost::shared_ptr boost::make_shared(CONST_REFERENCE(ARG_TYPE1), CONST_REFERENCE(ARG_TYPE2), CONST_REFERENCE(ARG_TYPE3), CONST_REFERENCE(ARG_TYPE4), CONST_REFERENCE(ARG_TYPE5), CONST_REFERENCE(ARG_TYPE6)), CONST_REFERENCE(ARG_TYPE7)), CONST_REFERENCE(ARG_TYPE8)) #define BOOST_MAKE_SHARED_9ARG_CONSTRUCTOR(CLASS_NAME, ARG_TYPE1, ARG_TYPE2, ARG_TYPE3, ARG_TYPE4, ARG_TYPE5, ARG_TYPE6, ARG_TYPE7, ARG_TYPE8, ARG_TYPE9) \ friend boost::shared_ptr boost::make_shared(CONST_REFERENCE(ARG_TYPE1), CONST_REFERENCE(ARG_TYPE2), CONST_REFERENCE(ARG_TYPE3), CONST_REFERENCE(ARG_TYPE4), CONST_REFERENCE(ARG_TYPE5), CONST_REFERENCE(ARG_TYPE6)), CONST_REFERENCE(ARG_TYPE7)), CONST_REFERENCE(ARG_TYPE8)), CONST_REFERENCE(ARG_TYPE9)).

Just a summary of how a complete version may look like: #include #include class Foo { explicit Foo(int x) { std::cout boost::make_shared(const int& x); static boost::shared_ptr create(int x) { return boost::make_shared(x); } ~Foo() { std::cout.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions