#pragma once

template<typename FuncType>
class scope_exit_guard {
public:
    scope_exit_guard(FuncType&& in_func) : func((FuncType&&)in_func) {
    }
    virtual ~scope_exit_guard() {
        func();
    }
private:
    FuncType func;
};

struct scope_exit_syntax_support {
    virtual ~scope_exit_syntax_support() = default;
    template <typename FuncType>
    scope_exit_guard<FuncType> operator+(FuncType&& InFunc)
    {
        return scope_exit_guard<FuncType>((FuncType&&)InFunc);
    }
};

#define PRIVATE_CONCATENATE_DETAIL(x, y) x##y
#define PRIVATE_CONCATENATE(x, y) PRIVATE_CONCATENATE_DETAIL(x, y)

#define ON_SCOPE_EXIT const auto PRIVATE_CONCATENATE(scope_exit, __LINE__) = scope_exit_syntax_support() + [&]()

