Reputation: 8805
I simply want to use the deleter feature of a shared_ptr without using the shared_ptr part. As in, I want to call a function when the shared_ptr goes out of scope and the deleter doesn't need any pointer passed to it.
I have this but it's cheezy.
shared_ptr<int> x(new int, [&](int *me) { delete me; CloseResource(); });
Is there a way to not associate any pointer with the shared_ptr?
Update: as per many suggestions, the unique_ptr way would look like this:
unique_ptr<int, std::function<void(int*)>> x(new int, [&](int *me) {delete me; CloseResource();});
Which frankly looks worse than the shared_ptr version, as much 'better' as it is.
Update: for those who like using this simple scope closing function caller I made it a bit simpler, you don't even need to allocate or free an object:
shared_ptr<int> x(NULL, [&](int *) { CloseResource(); });
Upvotes: 3
Views: 1304
Reputation: 10875
It sounds like what you may be trying to do is turn over "delete" responsibilities to "somebody else" so you no longer have to worry about it. If that's the case, unique_ptr
(not shared_ptr
) with a custom deleter will work:
struct Foo final {};
Foo* New() { return new Foo; }
void Delete(Foo* p) { delete p; }
int main()
{
auto p = New();
std::unique_ptr<Foo, decltype(&Delete)> up(p, &Delete);
}
There are a number of similar solutions listed here; there's not much more that can be done without more information about your actual API (e.g., does the HANDLE
is really a pointer trick work?). And even more reading at The simplest and neatest c++11 ScopeGuard, including a link to a proposed std::unique_resource
.
Upvotes: 3
Reputation: 657
If you want a RAII like semantics with a lambda maybe something like this will do the job?
namespace details {
enum class ScopeExitDummy { };
}
template<typename T>
class scope_exit_t
{
public:
inline scope_exit_t(T&& codeChunk_)
: m_codeChunk(std::forward<T>(codeChunk_)) {
}
inline scope_exit_t(scope_exit_t<T>&& rhs_)
: m_codeChunk(std::move(rhs_.m_codeChunk))
{
}
~scope_exit_t() {
m_codeChunk();
}
private:
T m_codeChunk;
};
template<typename T>
inline scope_exit_t<T> operator+(details::ScopeExitDummy, T&& functor_) {
return scope_exit_t<T>{std::forward<T>(functor_)};
}
#define AtScopeExit auto TW_UNIQUE_VARIABLE(_scopeExit) = details::ScopeExitDummy{} + [&]
And usage is like:
AtScopeExit {
CloseResource();
};
Note: TW_UNIQUE_VARIABLE is just a macro that generares a unique variable name so that the code does not clash with hand-written declarations.
#define TW_STR_CONCAT_IMPL(x, y) x##y
#define TW_STR_CONCAT(x, y) TW_STR_CONCAT_IMPL(x, y)
#ifdef __COUNTER__
#define TW_UNIQUE_VARIABLE(prefix) TW_STR_CONCAT(prefix, __COUNTER__)
#else
#define TW_UNIQUE_VARIABLE(prefix) TW_STR_CONCAT(prefix, __LINE__)
#endif
Upvotes: 0