• Do you like that ?

    From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Mon Mar 2 08:22:27 2026
    From Newsgroup: comp.lang.c++

    template<typename T>
    struct exc_obj : std::expected<T, std::exception_ptr>
    {
    using super = std::expected<T, std::exception_ptr>;
    template<typename ... Args>
    exc_obj( Args &&... args );
    };

    template<typename T>
    template<typename ... Args>
    exc_obj<T>::exc_obj( Args &&... args ) :
    super( [&]() -> super
    {
    try
    {
    return T( std::forward<Args>( args ) ... );
    }
    catch( ... )
    {
    return std::unexpected( std::current_exception() );
    }
    }() )
    {
    }

    Object that encapsulates the given class or exception if needed
    in an C++23 std::expected.

    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c++ on Mon Mar 2 08:25:53 2026
    From Newsgroup: comp.lang.c++

    My own std::barrier-variant. Slightly simpler than the original.
    And the completion function can return a value.

    struct xarrival_token
    {
    xarrival_token() noexcept = default;
    xarrival_token( const xarrival_token &tk ) noexcept = default;
    xarrival_token &operator =( const xarrival_token &tk ) noexcept = default;
    private:
    template<std::invocable Complete>
    friend struct xbarrier;
    int m_id = -1;
    };

    template<std::invocable Complete>
    struct xbarrier
    {
    static constexpr bool WithReturn = !std::same_as<std::invoke_result_t<Complete>, void>;
    using arrive_result = std::conditional_t<WithReturn, std::optional<std::invoke_result_t<Complete>>, void>;
    xbarrier( unsigned initial, Complete &&complete );
    xbarrier( const xbarrier & ) = delete;
    xbarrier &operator =( const xbarrier & ) = delete;
    arrive_result arrive( xarrival_token &tk, bool drop = false );
    private:
    std::mutex m_mtx;
    xcondition_variable m_cv;
    unsigned m_initial, m_ctr;
    bool m_genFlip;
    NO_UNIQUE_ADDRESS Complete m_complete;
    };

    template<std::invocable Complete>
    xbarrier<Complete>::xbarrier( unsigned initial, Complete &&complete ) :
    m_initial( initial ),
    m_ctr( initial ),
    m_complete( std::forward<Complete>( complete ) )
    {
    if constexpr( requires { (bool)m_complete; } )
    assert((bool)m_complete);
    }

    template<std::invocable Complete>
    auto xbarrier<Complete>::arrive( xarrival_token &tk, bool drop ) -> arrive_result
    {
    using namespace std;
    unique_lock lock( m_mtx );
    assert(m_ctr <= m_initial);
    if( !m_initial )
    return (arrive_result)nullopt;
    m_initial -= drop;
    unsigned newId = --m_ctr;
    if( bool gen = m_genFlip; m_ctr )
    m_cv.wait( lock, [&] { return m_genFlip != gen; } );
    else
    {
    m_ctr = m_initial;
    m_genFlip = !gen;
    m_cv.notify_all();
    }
    if( tk.m_id < 0 )
    tk.m_id = newId;
    if( !tk.m_id )
    return m_complete();
    return (arrive_result)nullopt;
    }
    --- Synchronet 3.21d-Linux NewsLink 1.2