рдореИрдВрдиреЗ рд╣рд╛рд▓ рд╣реА рдореЗрдВ C ++ Variadic Templates рдХреЛ рдирд┐рдХрдЯ рд╕реЗ рджреЗрдЦрд╛ рдФрд░ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд░реВрдк рд╕реЗ рдирдП RAII рд╕реНрдХреЛрдкреНрдб рд░рд┐рд╕реЛрд░реНрд╕ рдореИрдиреЗрдЬрд░ рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХрд┐рдпрд╛ред
рдпрд╣ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдФрд░ рдкреНрд░рднрд╛рд╡реА рд░реВрдк рд╕реЗ рдирд┐рдХрд▓рд╛ред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, C- рд╢реИрд▓реА рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрди рдХреЗ рд╕рд╛рде:
рдЬрдм рдЖрдк рдмреНрд▓реЙрдХ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддреЗ рд╣реИрдВ, рддреЛ рд╕рдВрд╕рд╛рдзрди рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдореБрдХреНрдд рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
рдпрд╛ рдлрд┐рд░ рдЗрд╕ рддрд░рд╣, рдЖрдк рдлрд╝рд╛рдЗрд▓ рдбрд┐рд╕реНрдХреНрд░рд┐рдкреНрдЯрд░ рд╕рдВрд╕рд╛рдзрди рдХреЗ рд╕реНрд╡рд╛рдорд┐рддреНрд╡ рдХреЛ рд╣рдбрд╝рдк рд╕рдХрддреЗ рд╣реИрдВ:
рдЬрдм рдЖрдк рдмреНрд▓реЙрдХ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддреЗ рд╣реИрдВ, рддреЛ рдХреЙрд▓ рдХреЗ рдмрд╛рдж рднреА рд╕рдВрд╕рд╛рдзрди рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЬрд╛рд░реА рд╣реЛ рдЬрд╛рдПрдЧрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
throw std::exception()
ред
рдпрд╛ рджреВрд╕рд░реЗ рдЙрджрд╛рд╣рд░рдг рдХреЛ рд▓рдВрдмреЛрджрд░ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдмрд┐рдирд╛ рдФрд░ рднреА рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
{ ha::scoped_resource<int, char*, int> fd(::open, filename.c_str(), O_RDONLY, ::close); if (fd == -1) throw std::runtime_error(std::string("open() failed: ") + ::strerror(errno)); std::vector<char> buff(1024); ssize_t rc = ::read(fd, &buff[0], 1024); }
рдпрд╣реА рд╣реИ, рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХреНрд▓рд╛рд╕ рд╣реИ рдЬреЛ рд╕рдВрд╕рд╛рдзрди рдкреНрд░рдХрд╛рд░ рджреНрд╡рд╛рд░рд╛ рддреНрд╡рд░рд┐рдд рд╣реИ, рдФрд░ рдЗрд╕рдХрд╛ рдирд┐рд░реНрдорд╛рддрд╛ рджреЛ
std::functions
:
initializer_t finalizer_t
рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИред
рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ рдФрд░ рдлрд╝рд╛рдЗрдирд▓реАрдЬрд╝рд░ рдХреЗ рдмреАрдЪ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИрдВ, рдЬреЛ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдХреНрд╡рд╛рд▓реАрдлрд╝рд╛рдпрд░ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИрдВред
рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдХреИрдж рдХрд┐рдП рдЧрдП рд╕рдВрд╕рд╛рдзрди рдХреЗ рд▓рд┐рдП рдЕрдВрддрд┐рдо рд░реВрдк рд╕реЗ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред
рд╕рдВрд╕рд╛рдзрди рддрдХ рдХрдЪреНрдЪреЗ рдкрд╣реБрдВрдЪ рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕рдВрд╕рд╛рдзрди рдкреНрд░рдХрд╛рд░ рдСрдкрд░реЗрдЯрд░ рдореМрдЬреВрдж рд╣реИред
{ ha::scoped_resource <resource_t, param1_t, ...> resource (ititializer, param1, ..., finalizer); resource_t plain_resource = resource.operator resource_t(); }
рд╕рдВрд╕рд╛рдзрди рд░реИрдкрд░ рдХреЗ рдЕрдиреНрдп рдЖрд░рдПрдЖрдИ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкрд░ рдХреНрдпрд╛ рд▓рд╛рдн рд╣реИ?
- рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдорд╛рдкрджрдВрдбреЛрдВ рдореЗрдВ рдХрдореА рдХреЗ рджреМрд░рд╛рди рдЗрдирд┐рд╢рд▓рд╛рдЗрдЬрд╝рд░ рдХреЛ рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рд╣реАред рдпрд╣, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ "рд╕рд╛рдорд╛рдиреНрдп" рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ рдЯреНрд░рд╛рдВрд╕рдлрд╝рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреЛ
operator resource_t()
рд▓рд┐рдП рдкрд╣рд▓реА рдХреЙрд▓ рд╕реЗ рдкрд╣рд▓реЗ рдЖрд▓рд╕реА-рд╢реИрд▓реА рдореЗрдВ рдПрдХ рд╕рдВрд╕рд╛рдзрди рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛рддрд╛ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рдирд╛рдорд╛рдВрдХрд┐рдд рдирд╛рдорд╛рдВрдХрд┐рдд рдмрдирд╛рдиреЗ рдХреА рднреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЙрдирдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред - рдЖрдк рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд░реВрдк рд╕реЗ рдХрд┐рд╕реА рднреА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ, рд╢рд╛рдпрдж, рдПрдХ рдФрд░ рджреВрд╕рд░рд╛ рдЙрдкрдпреЛрдЧреА рддрдВрддреНрд░ рд╣реИ -
std::initializer_list
ред - рдпрджрд┐ рдмрд┐рдВрджреБ 2. рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдПрдХ рд▓реИрдореНрдмрдбрд╛ рдХреЛ рдПрдХ рдЗрдирд┐рд╢рд▓рд╛рдЗрдЬрд╝рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝рд░ рдХреЗ рд╕рднреА рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдмрдВрдж рдХрд░ рджреЗрддрд╛ рд╣реИред
- рдбрд┐рдирд╛рдпрдЯрд┐рд▓рд╛рдЗрдЬрд╝рд░ рдХреЗ рдкрд╛рд╕ рдПрдХ рдПрдХрд▓ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ - рд╕рдВрд╕рд╛рдзрди рдХрд╛ рдкреНрд░рдХрд╛рд░, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдпрд╣ рдПрдХ рд▓реИрдореНрдмреНрдбрд╛ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдбрд┐рдирд╛рдЗрдирд┐рдЯрд╛рдЗрдЬреЗрд╢рди рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдорд╛рдкрджрдВрдбреЛрдВ рдкрд░ рд▓реЙрдХ рдХрд░ рд╕рдХрддрд╛ рд╣реИред
- рдЗрд╕реЗ
std::shared_ptr(T* ptr, deleter d)
рд╕реЗ рдЕрдзрд┐рдХ рдЖрд╕рд╛рдиреА рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ std::shared_ptr(T* ptr, deleter d)
ред
рдиреБрдХрд╕рд╛рди?
рдХрднреА-рдХрднреА рдкреВрд░реНрдг рд╕рдВрд╕рд╛рдзрди рдЖрд╡рд░рдг рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдЕрднреА рднреА рдЕрдзрд┐рдХ рдХреБрд╢рд▓ рд╣реИред
рдФрд░ рдЙрджрд╛рд╣рд░рдг рдЪрд╛рд╣рд┐рдП? рдореИрдВрдиреЗ рдЙрдиреНрд╣реЗрдВ:
рдПрдХ AVFormatContext рд╕рдВрджрд░реНрдн рдмрдирд╛рдирд╛:
ha::scoped_resource<ffmpeg::AVFormatContext*> formatctx (ffmpeg::avformat_alloc_context, ffmpeg::avformat_free_context);
рдпрд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛ рдПрдХ рдПрдирд╛рд▓реЙрдЧ рд╣реИ:
std::shared_ptr<ffmpeg::AVFormatContext> formatctx = std::shared_ptr<ffmpeg::AVFormatContext> (ffmpeg::avformat_alloc_context(), ffmpeg::avformat_free_context);
рдпрд╛ рдлрд┐рд░, рдПрдХ рд╕рдореНрдорд┐рд╢реНрд░ deinitializer рдпрд╣рд╛рдБ рдкреНрд░рдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
ha::scoped_resource<ffmpeg::AVCodecContext*> codecctx( ffmpeg::avcodec_alloc_context, [](ffmpeg::AVCodecContext* c) { ffmpeg::avcodec_close(c), ffmpeg::av_free(c); });
рдФрд░ рдпрд╣ рдЙрджрд╛рд╣рд░рдг рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдХрд┐ рдПрдХ рд╕рдВрд╕рд╛рдзрди рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдореБрдХреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ:
ha::scoped_resource<ffmpeg::AVCodec*, ffmpeg::AVCodecID> codec( ffmpeg::avcodec_find_decoder, codecctx->codec_id, [](__attribute__((unused)) ffmpeg::AVCodec* c) { });
рдФрд░ рдЕрдВрдд рдореЗрдВ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рдСрдирд▓рд╛рдЗрдирд░:
ha::scoped_resource<ffmpeg::AVFrame*> frame(ffmpeg::avcodec_alloc_frame, ffmpeg::av_free);
рдЬреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИ:
std::shared_ptr<ffmpeg::AVFrame> frame = std::shared_ptr<ffmpeg::AVFrame>(ffmpeg::avcodec_alloc_frame(), ffmpeg::av_free);
рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдирдЧреНрди рд╕рд╛рджреЗ-рд╕реА рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИ? рдФрд░ рдорд╛рдиреНрдп C ++ рд╡рд╛рд▓реЗ рдЙрджрд╛рд╣рд░рдг рдХрд╣рд╛рдВ рд╣реИрдВ?
рдФрд░ рдпрд╣рд╛рдБ:
ha::mutex mutex; ha::scoped_resource<ha::mutex*, ha::mutex*> scoped_lock( [](ha::mutex* m) -> ha::mutex* { return m->lock(), m; }, &mutex, [](ha::mutex* m) -> void { m->unlock(); } );
рдареАрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╣рд╛рдВ рд╣реИ?
Scoped_resource рд╡рд░реНрдЧ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЗрддрдирд╛ рд╕рд░рд▓ рдФрд░ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдЗрд╕рдиреЗ рдореБрдЭреЗ
рд╡рд╛рдИ-рдХреЙрдореНрдмрд┐рдиреЗрдЯрд░ рдХреЗ рд╡рд┐рдЪрд╛рд░ рдХреЛ рднреА рдпрд╛рдж рджрд┐рд▓рд╛рдпрд╛ред
рдпрд╣реА рд╣реИ, рдпрд╣ рдЖрд╕рд╛рдиреА рд╕реЗ рдХреБрдЫ рд╕рдорд╛рди рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╡ рд╣реИ, рдмрд╕ рдирд┐рд░реНрдорд╛рддрд╛
scoped_resource::scoped_resource(initializer_t, finalizer_t);
рдХреА рдШреЛрд╖рдгрд╛ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ
scoped_resource::scoped_resource(initializer_t, finalizer_t);
рдФрд░ рдлрд┐рд░ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд▓рд┐рдП рд╡реИрд░реЗрдбрд┐рдХ рднрд╛рдЧ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВред
рдареАрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡реИрд╕реЗ рднреА рдХрд╣рд╛рдБ рд╣реИ, рд╣реБрд╣?
template <typename T, typename... A> class scoped_resource { public: typedef std::function<T (A...)> initializer_t; typedef std::function<void(T)> finalizer_t; typedef T resource_t; scoped_resource(initializer_t finit, A... args, finalizer_t final) : finit_(finit), final_(final), resource_(finit_(args...)) { }; ~scoped_resource() { final_(resource_); } template <typename Y> Y get() const { return static_cast<Y>(resource_); } T get() const { return resource_; } operator T() const { return get(); }
рдХреБрдЫ рдЗрд╕ рддрд░рд╣ред
