shared_instance implementation using C++ and RAII

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite












I created a little singleton-like class that gets deleted when there is no reference to it anymore (so its lifetime shall be somewhat predictable). I aimed to make it thread-safe.



#include <memory>
#include <mutex>

template< typename t_type >
struct shared_instance

static std::shared_ptr< t_type > get_shared_instance()

static std::weak_ptr< t_type > weak;
static std::mutex mutex;

auto result = weak.lock();
if( nullptr == result )

std::unique_lock< std::mutex > lock mutex ;

result = weak.lock();
if( nullptr != result )

return result;


result = std::make_shared< t_type >();
weak = result;

return result;

;

template< typename t >
struct context

context()
: instance shared_instance< t >::get_shared_instance()


private: std::shared_ptr< t > instance;
;


I would be glad if you could comment on the implementation itself and how I could tackle non-default-constructible objects (I know of perfect forwarding and variadic templates but I have not found an elegant way to evaluate them lazily).







share|improve this question





















  • Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
    – WooWapDaBug
    Jan 29 at 12:58










  • yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations like context c1; /*some code here*/; context c2; c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instance
    – cubber
    Jan 29 at 14:16











  • so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
    – cubber
    Jan 29 at 14:23
















up vote
3
down vote

favorite












I created a little singleton-like class that gets deleted when there is no reference to it anymore (so its lifetime shall be somewhat predictable). I aimed to make it thread-safe.



#include <memory>
#include <mutex>

template< typename t_type >
struct shared_instance

static std::shared_ptr< t_type > get_shared_instance()

static std::weak_ptr< t_type > weak;
static std::mutex mutex;

auto result = weak.lock();
if( nullptr == result )

std::unique_lock< std::mutex > lock mutex ;

result = weak.lock();
if( nullptr != result )

return result;


result = std::make_shared< t_type >();
weak = result;

return result;

;

template< typename t >
struct context

context()
: instance shared_instance< t >::get_shared_instance()


private: std::shared_ptr< t > instance;
;


I would be glad if you could comment on the implementation itself and how I could tackle non-default-constructible objects (I know of perfect forwarding and variadic templates but I have not found an elegant way to evaluate them lazily).







share|improve this question





















  • Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
    – WooWapDaBug
    Jan 29 at 12:58










  • yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations like context c1; /*some code here*/; context c2; c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instance
    – cubber
    Jan 29 at 14:16











  • so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
    – cubber
    Jan 29 at 14:23












up vote
3
down vote

favorite









up vote
3
down vote

favorite











I created a little singleton-like class that gets deleted when there is no reference to it anymore (so its lifetime shall be somewhat predictable). I aimed to make it thread-safe.



#include <memory>
#include <mutex>

template< typename t_type >
struct shared_instance

static std::shared_ptr< t_type > get_shared_instance()

static std::weak_ptr< t_type > weak;
static std::mutex mutex;

auto result = weak.lock();
if( nullptr == result )

std::unique_lock< std::mutex > lock mutex ;

result = weak.lock();
if( nullptr != result )

return result;


result = std::make_shared< t_type >();
weak = result;

return result;

;

template< typename t >
struct context

context()
: instance shared_instance< t >::get_shared_instance()


private: std::shared_ptr< t > instance;
;


I would be glad if you could comment on the implementation itself and how I could tackle non-default-constructible objects (I know of perfect forwarding and variadic templates but I have not found an elegant way to evaluate them lazily).







share|improve this question













I created a little singleton-like class that gets deleted when there is no reference to it anymore (so its lifetime shall be somewhat predictable). I aimed to make it thread-safe.



#include <memory>
#include <mutex>

template< typename t_type >
struct shared_instance

static std::shared_ptr< t_type > get_shared_instance()

static std::weak_ptr< t_type > weak;
static std::mutex mutex;

auto result = weak.lock();
if( nullptr == result )

std::unique_lock< std::mutex > lock mutex ;

result = weak.lock();
if( nullptr != result )

return result;


result = std::make_shared< t_type >();
weak = result;

return result;

;

template< typename t >
struct context

context()
: instance shared_instance< t >::get_shared_instance()


private: std::shared_ptr< t > instance;
;


I would be glad if you could comment on the implementation itself and how I could tackle non-default-constructible objects (I know of perfect forwarding and variadic templates but I have not found an elegant way to evaluate them lazily).









share|improve this question












share|improve this question




share|improve this question








edited Feb 7 at 0:05









Jamal♦

30.1k11114225




30.1k11114225









asked Jan 28 at 16:16









cubber

184




184











  • Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
    – WooWapDaBug
    Jan 29 at 12:58










  • yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations like context c1; /*some code here*/; context c2; c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instance
    – cubber
    Jan 29 at 14:16











  • so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
    – cubber
    Jan 29 at 14:23
















  • Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
    – WooWapDaBug
    Jan 29 at 12:58










  • yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations like context c1; /*some code here*/; context c2; c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instance
    – cubber
    Jan 29 at 14:16











  • so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
    – cubber
    Jan 29 at 14:23















Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
– WooWapDaBug
Jan 29 at 12:58




Aren't singleton-like things usually a bad idea? What are you aiming for with this, I'm curious.
– WooWapDaBug
Jan 29 at 12:58












yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations like context c1; /*some code here*/; context c2; c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instance
– cubber
Jan 29 at 14:16





yeah they are. however, i need a kind of context-object: using raii to call c-style functions like create (in ctor) and destroy (in dtor). i need to make sure that that context exists as long as i'm using some ressources in that context. the problem is in situations like context c1; /*some code here*/; context c2; c2 will tear down the context but it c1 should (braoder scope, calling the create-function mutliple times is not an error from the c-library's point of view). i need a way to make sure that behind the scenes there is only one call to destroy in the dtor of the last instance
– cubber
Jan 29 at 14:16













so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
– cubber
Jan 29 at 14:23




so this is not really a classical singleton that is used to share an instance but rather to make sure that client-code can not accidentally misuse the library code and it remains exception-safe. if there are any other suggestions of how i could accomplish this, let me know, i'd be very happy. by the way: the returned shared_pointer is then hidden in the context-object which acts as kind of a contract meaning that the init/create/.. function was called and that it will be cleaned up extactly once when that context is not referenced anywhere anymore.
– cubber
Jan 29 at 14:23










1 Answer
1






active

oldest

votes

















up vote
2
down vote



accepted










Non-Default Constructors:



Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.



template< typename t_type >
struct shared_instance

using t_factory = std::function<std::shared_ptr< t_type >()>;

static t_factory factory; // MUST be set before calling get_shared_instance

static std::shared_ptr< t_type > get_shared_instance()

...


assert(factory); // or throw, or return empty shared_ptr

result = factory(); // instead of make_shared

...


;

// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;


...

int main()

context<int> c; // not ok... haven't set factory yet!

// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...

context<int> c; // ok



I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:



template< typename t >
struct context

context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()


private:

std::shared_ptr< t > instance;
;

int main()

auto provider = instance_provider<int>( () return std::make_shared<int>(5); );

context<int> c(provider);



Further Considerations:



Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)



The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?



If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.






share|improve this answer





















  • if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
    – cubber
    Feb 8 at 11:28










  • i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
    – cubber
    Feb 8 at 11:31










Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186204%2fshared-instance-implementation-using-c-and-raii%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
2
down vote



accepted










Non-Default Constructors:



Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.



template< typename t_type >
struct shared_instance

using t_factory = std::function<std::shared_ptr< t_type >()>;

static t_factory factory; // MUST be set before calling get_shared_instance

static std::shared_ptr< t_type > get_shared_instance()

...


assert(factory); // or throw, or return empty shared_ptr

result = factory(); // instead of make_shared

...


;

// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;


...

int main()

context<int> c; // not ok... haven't set factory yet!

// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...

context<int> c; // ok



I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:



template< typename t >
struct context

context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()


private:

std::shared_ptr< t > instance;
;

int main()

auto provider = instance_provider<int>( () return std::make_shared<int>(5); );

context<int> c(provider);



Further Considerations:



Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)



The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?



If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.






share|improve this answer





















  • if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
    – cubber
    Feb 8 at 11:28










  • i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
    – cubber
    Feb 8 at 11:31














up vote
2
down vote



accepted










Non-Default Constructors:



Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.



template< typename t_type >
struct shared_instance

using t_factory = std::function<std::shared_ptr< t_type >()>;

static t_factory factory; // MUST be set before calling get_shared_instance

static std::shared_ptr< t_type > get_shared_instance()

...


assert(factory); // or throw, or return empty shared_ptr

result = factory(); // instead of make_shared

...


;

// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;


...

int main()

context<int> c; // not ok... haven't set factory yet!

// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...

context<int> c; // ok



I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:



template< typename t >
struct context

context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()


private:

std::shared_ptr< t > instance;
;

int main()

auto provider = instance_provider<int>( () return std::make_shared<int>(5); );

context<int> c(provider);



Further Considerations:



Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)



The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?



If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.






share|improve this answer





















  • if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
    – cubber
    Feb 8 at 11:28










  • i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
    – cubber
    Feb 8 at 11:31












up vote
2
down vote



accepted







up vote
2
down vote



accepted






Non-Default Constructors:



Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.



template< typename t_type >
struct shared_instance

using t_factory = std::function<std::shared_ptr< t_type >()>;

static t_factory factory; // MUST be set before calling get_shared_instance

static std::shared_ptr< t_type > get_shared_instance()

...


assert(factory); // or throw, or return empty shared_ptr

result = factory(); // instead of make_shared

...


;

// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;


...

int main()

context<int> c; // not ok... haven't set factory yet!

// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...

context<int> c; // ok



I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:



template< typename t >
struct context

context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()


private:

std::shared_ptr< t > instance;
;

int main()

auto provider = instance_provider<int>( () return std::make_shared<int>(5); );

context<int> c(provider);



Further Considerations:



Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)



The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?



If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.






share|improve this answer













Non-Default Constructors:



Adding support for non-default constructible objects in a "lazy" fashion, could be done by adding a factory function of std::function<std::shared_ptr< t_type >()>.



template< typename t_type >
struct shared_instance

using t_factory = std::function<std::shared_ptr< t_type >()>;

static t_factory factory; // MUST be set before calling get_shared_instance

static std::shared_ptr< t_type > get_shared_instance()

...


assert(factory); // or throw, or return empty shared_ptr

result = factory(); // instead of make_shared

...


;

// and define the static member...
template< typename t_type >
typename shared_instance< t_type >::t_factory shared_instance< t_type >::factory;


...

int main()

context<int> c; // not ok... haven't set factory yet!

// do this before any call to get_shared_instance
shared_instance<int>::factory = () return std::make_shared<int>(5); ; // store things in the lambda by value, not reference...

context<int> c; // ok



I'm not sure this counts as elegant though, as it gives you a two-step initialization process. This could be fixed by recognising the shared_instance itself as a kind of factory, making its contents non-static, and passing it into the contexts:



template< typename t >
struct context

context(instance_provider< t >& provider): // now it can't be created unless this exists...
instance provider.get_shared_instance()


private:

std::shared_ptr< t > instance;
;

int main()

auto provider = instance_provider<int>( () return std::make_shared<int>(5); );

context<int> c(provider);



Further Considerations:



Does the C library you're using say anything about context lifetime itself? (e.g. Winsock reference counts calls to WSAStartup() and WSACleanup() internally, so as long as the calls are paired properly the C library handles cleaning up)



The main feature that this shared_instance class seems to provide is destroying The Instance promptly after the last context is destroyed. RAII itself could be achieved by just storing a unique pointer over the maximum possible lifetime of any contexts, which would be simpler. Is this prompt destruction actually important?



If not, then it's just a singleton, which we either live with, or do the work to pass a pointer or reference to the thing you need where it needs to be.







share|improve this answer













share|improve this answer



share|improve this answer











answered Feb 6 at 20:05









user673679

1,042518




1,042518











  • if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
    – cubber
    Feb 8 at 11:28










  • i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
    – cubber
    Feb 8 at 11:31
















  • if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
    – cubber
    Feb 8 at 11:28










  • i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
    – cubber
    Feb 8 at 11:31















if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
– cubber
Feb 8 at 11:28




if i understood your second approach correctly, i could just create context<> c1provider and context<> c2provider which would both call the ctor of the context-type and the dtor of the context-type, so it might happen that objects have a context-member created from c1 while c2 already called the teardown-function, right? passing in a lambda for lazy execution is a good idea when retreiving the parameters of the lambda is more expensive than the whole concept itself, setting the required params statically before calls to get_shared_instance() is propably cheapest (and the ugiest one) :)
– cubber
Feb 8 at 11:28












i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
– cubber
Feb 8 at 11:31




i'm still marking your answer as accepted because of your efforts and additional input in further considerations. after all, my question was how to decorate an anti-pattern which can not be done much nicer than you suggested i suppse, thanks again for all your effort and considerations!
– cubber
Feb 8 at 11:31












 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186204%2fshared-instance-implementation-using-c-and-raii%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Python Lists

Aion

JavaScript Array Iteration Methods