c++ - How can I implement this autoscope template object better? -


i have idea auto-scoped type clean resources when leave scope or containing object destructed.

this currently:

template <typename resource, typename deleteor> struct autoscope {     resource m_resource;     deleteor const& m_deleteor;      autoscope(resource resource, deleteor const& deleteor)         : m_resource(resource)         , m_deleteor(deleteor)     {     }      operator resource()     {         return m_resource;     }      ~autoscope()     {         m_deleteor(m_resource);     } };  template <typename resource, typename deleteor> autoscope<resource, deleteor> make_autoscope(resource resource, deleteor deleteor) {     return autoscope<resource, deleteor>(resource, deleteor); } 

a couple of potential/real problems see/have come across.

  1. for each resource handled, there deletor object or pointer created. i'm not sure if optimizer junk , inline deletor functor or function pointer autoscope object not larger resource handle. i'm not sure compiler allowed to, don't think possible have deletor just passed type.

  2. i tried pass hicon , function pointer destroyicon() , crashed. when debugging showed pointer passed make_autoscope() 0x755225e0 {user32.dll!_destroycursor@4}, wrong. vc++ problem (2013)? or there else wrong?

i'm using vc++ in vs2013, should portable.

edit

ok, i've thought ideas based on comments. here i've come far:

template <typename resource, typename crtp, resource invalid> struct autoscope { protected:     resource m_res; public:     autoscope()         : m_res(invalid)     {     }      autoscope(resource res)         : m_res(res)     {     }      autoscope(autoscope&& move)     {         std::swap(move.m_res, m_res);     }      autoscope(autoscope& copy) = delete;      operator resource() const     {         return m_res;     }      resource get() const     {         return m_res;     }      resource operator =(resource res)     {         set(res);     }      void set(resource res)     {         static_cast<crtp*>(this)->delete_resource();         m_res = res;     }      resource release()     {         resource result = m_res;         m_res = invalid;         return result;     }      ~autoscope()     {         static_cast<crtp*>(this)->delete_resource();     }      operator bool() const     {         return m_res != (resource)0;     }      bool valid() const     {         return m_res != invalid;     } };  template <typename resource, bool(winapi *fn_delete)(resource), resource invalid = (resource)-1> struct autoscope_bool : public autoscope<resource, autoscope_bool<resource, fn_delete, invalid>, invalid> {     typedef autoscope<resource, autoscope_bool, invalid> base;     autoscope_bool()         : base(invalid)     {     }      autoscope_bool(resource res)         : base(res)     {     }      autoscope_bool(autoscope_bool&& move)         : base(std::forward<autoscope_bool>(move))     {     }      autoscope_bool(autoscope_bool& copy) = delete;      void delete_resource()     {         if (base::m_res && base::m_res != invalid)         {             verify(fn_delete(base::m_res));             base::m_res = invalid;         }     } };  template <typename resource, typename void(winapi *fn_delete)(resource), resource invalid = (resource)-1> struct autoscope_void : autoscope<resource, autoscope_void<resource, fn_delete, invalid>, invalid> {     typedef autoscope<resource, autoscope_void, invalid> base;     autoscope_void()         : base(invalid)     {     }      autoscope_void(resource res)         : base(res)     {     }      autoscope_void(autoscope_void&& move)         : base(std::forward<autoscope_void>(move))     {     }      autoscope_void(autoscope_void& copy) = delete;      void delete_resource()     {         if (m_res != invalid)         {             verify(fn_delete(m_res));             m_res = invalid;         }     } };  template <typename resource, typename functor_delete, resource invalid = (resource)-1> struct autoscope_functor : autoscope<resource, autoscope_functor<resource, functor_delete, invalid>, invalid> {     typedef autoscope<resource, autoscope_functor, invalid> base; private:     functor_delete m_functor_delete; public:     autoscope_functor(functor_delete functor_delete)         : autoscope(invalid)         , m_functor_delete(functor_delete)     {     }      autoscope_functor(resource res, functor_delete functor_delete)         : autoscope(res)         , m_functor_delete(functor_delete)     {     }      autoscope_functor(autoscope_functor&& move)         : base(std::forward<autoscope_functor>(move))         , m_functor_delete(move.m_functor_delete)     {     }      autoscope_functor(autoscope_functor& copy) = delete;      void delete_resource()     {         if (m_res != invalid)         {             m_functor_delete(m_res);             m_res = invalid;         }     } }; 

this needs lot of work.

  • the deleter shouldn't stored reference. that's recipe disaster, if fix make_autoscope take deleter reference. call make_autoscope lambda deleter, , code blows up.
  • the copy , move operations need fixing. default compiler-generated ones not suitable. class should not copyable, must move constructible (for make_autoscope work), , may or may not need move assignable.
  • the interface can use members, get(), reset(), , release().
  • i'm not sure there's point in worrying size of thing, can store deleter , resource in compressed pair if want. inlining, if deleter function pointer, , thing gets moved around, compiler may not able inline call. that's nothing new.

Comments

Popular posts from this blog

yii2 - Yii 2 Running a Cron in the basic template -

asp.net - 'System.Web.HttpContext' does not contain a definition for 'GetOwinContext' Mystery -

php - How do you embed a video into a custom theme on WordPress? -