AutoCloser.h

// AutoCloser.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2022

#pragma once
#ifndef Ceda_cxUtils_AutoCloser_H
#define Ceda_cxUtils_AutoCloser_H

#include "cxUtils.h"
#include "Detect.h"
#include "CedaAssert.h"
#include <memory>

namespace ceda
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// A smart pointer to automatically call Close() on its pointer when it destructs.
//
// Typically declared on the frame, ensuring that Close() is called, even when exceptions are 
// thrown
//
// Can be used to automatically close any "T" which has a Close() method or free function 
// (Streams, Files, etc)

template <typename T> using Close_method_t = decltype(std::declval<T&>().Close());
template <typename T> using has_Close_method = is_detected<Close_method_t, T>;

template<typename T>
struct Closer
{
    void operator()(T* p)
    {
        cxAssert(p != nullptr);
        if constexpr (has_Close_method<T>::value)
        {
            p->Close();
        }
        else
        {
            Close(p);
        }
    }
};

template<typename T>
using close_ptr = std::unique_ptr<T, Closer<T>>;

} // namespace ceda

#endif // include guard