Sujet : Re: encapsulating directory operations
De : Bonita.Montero (at) *nospam* gmail.com (Bonita Montero)
Groupes : comp.lang.cDate : 09. Jun 2025, 12:04:45
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <1026f3t$gfc6$3@raubtier-asyl.eternal-september.org>
References : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
User-Agent : Mozilla Thunderbird
Am 09.06.2025 um 09:59 schrieb Lawrence D'Oliveiro:
Not necessarily that simple. It might be easier if C++ had
try/finally (like Python does), but it doesn’t.
The initial thought with C++ exceptions is that all the unrolling
happens with RAII-classe so that you don't need finally. But some-
times you won't write a class for each resource you hold. For this
cases a helper-class like experimental::scope_exit is very comfor-
table. Unfortunately that's still not in the standard so that I
had to write it on my own:
#pragma once
#include <utility>
#include <concepts>
#include "nui.h"
template<std::invocable Fn>
struct defer final
{
defer( Fn &&fn ) :
m_enabled( true ),
m_fn( std::forward<Fn>( fn ) )
{
}
defer( defer const & ) = delete;
void operator =( defer const & ) = delete;
~defer()
{
if( m_enabled ) [[likely]]
m_fn();
}
void operator ()()
{
if( !m_enabled ) [[unlikely]]
return;
m_fn();
m_enabled = false;
}
void disable()
{
m_enabled = false;
}
private:
bool m_enabled;
NO_UNIQUE_ADDRESS Fn m_fn;
};
template<std::invocable ... Fns>
inline void disable( defer<Fns> &... defs )
{
(defs.disable(), ...);
}
template<std::invocable Fn, std::invocable FnNext = Fn>
struct xdefer final
{
xdefer( Fn &&fn, xdefer<FnNext> *next = nullptr ) :
m_enabled( true ),
m_next( next ),
m_fn( std::forward<Fn>( fn ) )
{
}
xdefer( xdefer const & ) = delete;
void operator =( xdefer const & ) = delete;
~xdefer()
{
bool enabled = m_enabled;
if( m_next ) [[likely]]
m_next->m_enabled = enabled;
if( enabled ) [[likely]]
m_fn();
}
void operator ()()
{
if( !m_enabled ) [[unlikely]]
return;
m_fn();
m_enabled = false;
if( !m_next ) [[unlikely]]
return;
m_next->m_enabled = true;
(*m_next)();
}
void disable()
{
m_enabled = false;
}
private:
template<std::invocable Fn1, std::invocable Fn2>
friend struct xdefer;
bool m_enabled;
xdefer<FnNext> *m_next;
NO_UNIQUE_ADDRESS Fn m_fn;
};