can_throw أم لا can_throw؟



الاستثناءات جزء من لغة C ++. جزء غامض منه. شخص ما لا يستخدمها من حيث المبدأ. لا يستخدمه على الإطلاق. من الكلمة على الإطلاق. لكن ليس نحن. نظرًا لأننا نعتبرها شيئًا مفيدًا للغاية ، فإنها تزيد بشكل كبير من موثوقية الكود.



لسوء الحظ ، لا يمكن استخدام جميع الاستثناءات في كل مكان. أولاً ، الاستثناءات ليست مجانية ، وثانيًا ، ليس كل رمز قادر على "النجاة" من حدوث الاستثناءات.



. , C++. , , C++ .



, noexcept. , , .



, C++, , .





C++ noexcept. noexcept / , / . , noexcept / , ( , swap, C- callback- ..).



, noexcept /. , - /, , . , :



void some_handler::on_read_result(
    const asio::error_code & ec,
    std::size_t bytes_transferred)
{
    if(!ec)
    {
        m_data_size = bytes_transferred;
        handle_data();
    }
    else
    {...}
}


handle_data , .



noexcept : / .



— , , . C++ - noexcept-. noexcept-. - :



void some_handler::on_read_result(
    const asio::error_code & ec,
    std::size_t bytes_transferred)
{
    noexcept
    {
        if(!ec)
        {
            m_data_size = bytes_transferred;
            handle_data();
        }
        else
        {...}
    }
}


. noexcept- noexcept-, . - , , .



, noexcept- C++ . , . . , .





, C++ , , . (callback-).



callback-, completion-handler- Asio. callback- , .. Asio . , completion-handler- — .



callback-, . , , .



callback-, Asio C- , try/catch, , :



void some_handler::on_read_result(
    const asio::error_code & ec,
    std::size_t bytes_transferred)
{
    try
    {
        handle_read_result(ec, bytes_transferred); //  .
    }
    catch(...)
    {
        //    "" .
    }
}


, , , ( ) callback try/catch handle_read_result. .



, , . .. , / , .



can_throw



can_throw, /. , can_throw, . /, can_throw.



, - callback- /, can_throw, .



, .. can_throw /. .. :



void some_handler::handle_read_result(
    can_throw_t can_throw,
    const asio::error_code & ec,
    std::size_t bytes_transferred)
{
    ... //      .
}

void some_handler::on_read_result(
    const asio::error_code & ec,
    std::size_t bytes_transferred)
{
    //     !
    handle_read_result(can_throw_t{}, ec, bytes_transferred);
}


, can_throw :



class can_throw_t
{
    friend class exception_handling_context_t;

    can_throw_t() noexcept = default;

public:
    ~can_throw_t() noexcept = default;

    can_throw_t( const can_throw_t & ) noexcept = default;
    can_throw_t( can_throw_t && ) noexcept = default;

    can_throw_t &
    operator=( const can_throw_t & ) noexcept = default;
    can_throw_t &
    operator=( can_throw_t && ) noexcept = default;
};


.. can_throw_t, " " (). , can_throw_t exception_handling_context_t:



class exception_handling_context_t
{
public:
    can_throw_t
    make_can_throw_marker() const noexcept { return {}; }
};


make_can_throw_marker()



void some_handler::on_read_result(
    const asio::error_code & ec,
    std::size_t bytes_transferred)
{
    try
    {
        exception_handling_context_t ctx;
        handle_read_result(ctx.make_can_throw_marker(), ec, bytes_transferred);
    }
    catch(...)
    {}
}


, exception_handling_context_t try/catch. . , wrap_throwing_action, , try, . - :



class can_throw_t
{
    //   can_throw  
    //   wrap_throwing_action.
    template<typename Lambda>
    friend void wrap_throwing_action(Lambda &&);

    can_throw_t() noexcept = default;

public:
    ... //    .
};

template< typename Lambda >
void wrap_throwing_action(Lambda && lambda)
{
    try
    {
        lambda(can_throw_t{});
    }
    catch(...)
    {}
}


.



can_throw_t exception_handling_context_t.



, callback- , , try.



, - / callback-, . , try . exception_handling_context_t :



some_handler::some_handler(
    std::vector<std::byte> initial_data,
    std::size_t initial_data_size)
    : m_data{std::move(initial_data)}
    , m_data_size{initial_data_size}
{
    exception_handling_context_t ctx;
    handle_data(ctx.make_can_throw_marker());
}
...
void some_handler::handle_read_result(
    can_throw_t can_throw,
    const asio::error_code & ec,
    std::size_t bytes_transferred)
{
    if(!ec)
    {
        m_data_size = bytes_transferred;
        handle_data(can_throw);
    }
    else
    {
        ...
    }
}
...
void some_handler::handle_data(can_throw_t)
{
    ... //   .
}


, catch: - , - "" ( callback- , ). wrap_throwing_action wrap_throwing_action.





" " . . : , . /, , , /.



, , - .



-, can_throw. .., , , . , , / . , , , .



-, can_throw . , , . .. callback-, can_throw , . can_throw callback- — callback- ( , callback-).



can_throw , can_throw . , can_throw . , , — .



, , , can_throw .





, , C++.



. , - ( RSDN) 15 . , , - .



, ++. can_throw. , :( .




All Articles