#include <iostream>
#include <tuple>
struct Result
{
Result() : m_success(true) {}
explicit operator bool() const { return !m_success; }
bool m_success;
};
template<unsigned index, typename... Types>
struct TupleItemDeleter
{
void operator() (std::tuple<Types...>& t)
{
std::cout << "Deleting item at index " << index << std::endl;
delete std::get<index>(t);
TupleItemDeleter<index - 1, Types...>{}(t);
}
};
template<typename... Types>
struct TupleItemDeleter<0, Types...>
{
void operator() (std::tuple<Types...>& t)
{
std::cout << "Deleting item at index 0" << std::endl;
delete std::get<0>(t);
}
};
template<typename... Types>
void deleter(std::tuple<Types...>& t)
{
constexpr auto tupleSize = std::tuple_size<std::tuple<Types...>>::value;
TupleItemDeleter<tupleSize - 1, Types...>{}(t);
}
template<typename... T>
struct CleanupHelper {
CleanupHelper (const Result& res, const std::tuple<T...>& itemsToDelete)
: m_result(res)
, m_itemsToDelete(itemsToDelete)
{
}
~CleanupHelper()
{
if(!m_result)
{
deleter(m_itemsToDelete);
}
}
const Result& m_result;
std::tuple<T...> m_itemsToDelete;
};
struct Foo {};
Result functionThatNeedsCleanup()
{
Result res;
Foo *pFoos_1, *pFoos_2;
CleanupHelper<Foo*,Foo*> cleanupHelper(res, std::make_tuple(pFoos_1, pFoos_2));
try
{
pFoos_1 = new Foo;
pFoos_2 = new Foo[10];
//
// Do work
//
}
catch(...)
{
res.m_success = false;
}
}
int main()
{
functionThatNeedsCleanup();
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHVwbGU+CgpzdHJ1Y3QgUmVzdWx0CnsKICAgIFJlc3VsdCgpIDogbV9zdWNjZXNzKHRydWUpIHt9CiAgICBleHBsaWNpdCBvcGVyYXRvciBib29sKCkgY29uc3QgeyByZXR1cm4gIW1fc3VjY2VzczsgfQogICAgYm9vbCBtX3N1Y2Nlc3M7Cn07Cgp0ZW1wbGF0ZTx1bnNpZ25lZCBpbmRleCwgdHlwZW5hbWUuLi4gVHlwZXM+CnN0cnVjdCBUdXBsZUl0ZW1EZWxldGVyCnsKICAgIHZvaWQgb3BlcmF0b3IoKSAoc3RkOjp0dXBsZTxUeXBlcy4uLj4mIHQpCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8ICJEZWxldGluZyBpdGVtIGF0IGluZGV4ICIgPDwgaW5kZXggPDwgc3RkOjplbmRsOwogICAgICAgIGRlbGV0ZSBzdGQ6OmdldDxpbmRleD4odCk7CiAgICAgICAgVHVwbGVJdGVtRGVsZXRlcjxpbmRleCAtIDEsIFR5cGVzLi4uPnt9KHQpOwogICAgfQp9OwoKdGVtcGxhdGU8dHlwZW5hbWUuLi4gVHlwZXM+CnN0cnVjdCBUdXBsZUl0ZW1EZWxldGVyPDAsIFR5cGVzLi4uPiAKewogICAgdm9pZCBvcGVyYXRvcigpIChzdGQ6OnR1cGxlPFR5cGVzLi4uPiYgdCkKICAgIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgIkRlbGV0aW5nIGl0ZW0gYXQgaW5kZXggMCIgPDwgc3RkOjplbmRsOwogICAgICAgIGRlbGV0ZSBzdGQ6OmdldDwwPih0KTsKICAgIH0KfTsKCnRlbXBsYXRlPHR5cGVuYW1lLi4uIFR5cGVzPgp2b2lkIGRlbGV0ZXIoc3RkOjp0dXBsZTxUeXBlcy4uLj4mIHQpCnsKICAgIGNvbnN0ZXhwciBhdXRvIHR1cGxlU2l6ZSA9IHN0ZDo6dHVwbGVfc2l6ZTxzdGQ6OnR1cGxlPFR5cGVzLi4uPj46OnZhbHVlOwogICAgVHVwbGVJdGVtRGVsZXRlcjx0dXBsZVNpemUgLSAxLCBUeXBlcy4uLj57fSh0KTsKfQoKCnRlbXBsYXRlPHR5cGVuYW1lLi4uIFQ+CnN0cnVjdCBDbGVhbnVwSGVscGVyIHsKCiAgICBDbGVhbnVwSGVscGVyIChjb25zdCBSZXN1bHQmIHJlcywgY29uc3Qgc3RkOjp0dXBsZTxULi4uPiYgaXRlbXNUb0RlbGV0ZSkKICAgICA6IG1fcmVzdWx0KHJlcykKICAgICAsIG1faXRlbXNUb0RlbGV0ZShpdGVtc1RvRGVsZXRlKQogICAgewogICAgfQoKICAgIH5DbGVhbnVwSGVscGVyKCkKICAgIHsKICAgICAgICBpZighbV9yZXN1bHQpCiAgICAgICAgewogICAgICAgICAgIGRlbGV0ZXIobV9pdGVtc1RvRGVsZXRlKTsKICAgICAgICB9CiAgICB9CiAgICAKICAgIGNvbnN0IFJlc3VsdCYgbV9yZXN1bHQ7CiAgICBzdGQ6OnR1cGxlPFQuLi4+IG1faXRlbXNUb0RlbGV0ZTsKfTsKCnN0cnVjdCBGb28ge307CgpSZXN1bHQgZnVuY3Rpb25UaGF0TmVlZHNDbGVhbnVwKCkKewoJUmVzdWx0IHJlczsKCUZvbyAqcEZvb3NfMSwgKnBGb29zXzI7CglDbGVhbnVwSGVscGVyPEZvbyosRm9vKj4gY2xlYW51cEhlbHBlcihyZXMsIHN0ZDo6bWFrZV90dXBsZShwRm9vc18xLCBwRm9vc18yKSk7Cgl0cnkKCXsKCQlwRm9vc18xID0gbmV3IEZvbzsKCQlwRm9vc18yID0gbmV3IEZvb1sxMF07CgkJLy8KCQkvLyBEbyB3b3JrCgkJLy8KCX0KCWNhdGNoKC4uLikKCXsKCQlyZXMubV9zdWNjZXNzID0gZmFsc2U7Cgl9Cn0KCmludCBtYWluKCkKewogIGZ1bmN0aW9uVGhhdE5lZWRzQ2xlYW51cCgpOwogIHJldHVybiAwOwp9