COMFRK 無料です
例えば Win32 Crypt API の CryptProtectData なんですけど、
DATA_BLOB output; ::CryptProtectData(&input, desc, NULL, NULL, NULL, 0, &output); shared_ptr<BYTE> ptr(output.pbData, ::LocalFree);
カスタムデリーターを使えば、オブジェクトをうっかり開放し損ねる、という悲劇を避けられてやったねなんですけど、これと対になる CryptUnprotectData なんですけど、
LPWSTR desc; DATA_BLOB output; ::CryptUnprotectData(&input, &desc, NULL, NULL, NULL, 0, &output); shared_ptr<BYTE> ptr(output.pbData, ::LocalFree); // can throw! shared_ptr<remove_pointer<LPWSTR>::type> ptr_(desc, ::LocalFree);
アチャー。複数開放しないといけないリソースを返してくれる API は困ります。
そこで variadic template なんですけど、
auto f() -> void { } template <typename P, typename D, typename... R> auto f(const P& p, const D& d, R... r) -> void { d(p); f(r...); } template <typename... T> struct s; template <> struct s<> { typedef tuple<> type; }; template <typename P, typename D, typename... R> struct s<P, D, R...> { typedef decltype( tuple_cat(declval<tuple<shared_ptr<typename remove_pointer<P>::type>>>(), declval<typename s<R...>::type>())) type; }; auto g() -> tuple<> { return make_tuple(); } template <typename P, typename D, typename... R> auto g(const P& p, const D& d, R... r) -> typename s<P, D, R...>::type { shared_ptr<typename remove_pointer<P>::type> ptr; try { ptr.reset(p, d); } catch (...) { f(r...); throw; } auto t = g(r...); return tuple_cat(make_tuple(ptr), t); }
グエーッこんな気持ちの悪いコードを書くんじゃない!大人は try catch を素直に使いましょう。
LPWSTR desc; DATA_BLOB output; ::CryptUnprotectData(&input, &desc, NULL, NULL, NULL, 0, &output); shared_ptr<BYTE> ptr; try { ptr.reset(output.pbData, ::LocalFree); } throw (...) { ::LocalFree(desc); throw; } shared_ptr<remove_pointer<LPWSTR>::type> ptr_(desc, ::LocalFree);
おしまい。
そんなわけで COMFRK vol1 の pdf がウェッブでダウンロードできるようになりましたから、読みましょう。
http://ratiwo.blogspot.com/2011/02/comfrk-free-dl.html