الاستثناءات جزء من لغة 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-, . - , , .
, 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. , :( .