mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Make call interfaces in etl::delegate and etl::closure conditionally noexcept (#1172)
* Make all call interfaces in etl::delegate conditionally noexcept This covers the case when the invoked code can throw. For operator(), this was already implemented. Do similarly for the other call interfaces. * Make all call interfaces in etl::closure conditionally noexcept Similar to etl::delegate, the contained delegate might be throwing. Apply the same solution as in etl::delegate to make the call interfaces conditionally noexcept.
This commit is contained in:
parent
92f07a66fc
commit
363d2e8ab5
@ -71,7 +71,7 @@ namespace etl
|
||||
/// \param f The delegate to be invoked.
|
||||
/// \param args The arguments to bind to the delegate.
|
||||
//*********************************************************************
|
||||
ETL_CONSTEXPR14 closure(const delegate_type& f, const TArgs... args) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 closure(const delegate_type& f, const TArgs... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
: m_f(f)
|
||||
, m_args(args...)
|
||||
{
|
||||
@ -81,7 +81,7 @@ namespace etl
|
||||
/// Invoke the stored delegate with the bound arguments.
|
||||
/// \return The result of the delegate invocation.
|
||||
//*********************************************************************
|
||||
ETL_CONSTEXPR14 TReturn operator()() const ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 TReturn operator()() const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
return execute(etl::index_sequence_for<TArgs...>{});
|
||||
}
|
||||
@ -94,7 +94,7 @@ namespace etl
|
||||
/// \param arg The new value to bind.
|
||||
//*********************************************************************
|
||||
template <size_t Index, typename UArg>
|
||||
ETL_CONSTEXPR14 void bind(UArg arg) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 void bind(UArg arg) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
static_assert(etl::is_convertible<UArg, etl::type_list_type_at_index_t<argument_types, Index>>::value, "Argument is not convertible");
|
||||
static_assert(!etl::is_reference<UArg>::value, "Cannot bind reference arguments");
|
||||
@ -108,7 +108,7 @@ namespace etl
|
||||
/// \param args The new values to bind.
|
||||
///*********************************************************************
|
||||
template <typename... UArgs>
|
||||
ETL_CONSTEXPR14 void bind(UArgs&&... args) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 void bind(UArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
static_assert(sizeof...(UArgs) == sizeof...(TArgs), "Argument count mismatch");
|
||||
bind_impl(etl::make_index_sequence<sizeof...(TArgs)>{}, etl::forward<UArgs>(args)...);
|
||||
@ -121,7 +121,7 @@ namespace etl
|
||||
/// \param args The new values to bind.
|
||||
///*********************************************************************
|
||||
template <size_t... Indexes, typename... UArgs>
|
||||
ETL_CONSTEXPR14 void bind_impl(etl::index_sequence<Indexes...>, UArgs&&... args) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 void bind_impl(etl::index_sequence<Indexes...>, UArgs&&... args) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
// Expand the pack and call bind<Index>(arg) for each argument
|
||||
int dummy[] = {0, (bind<Indexes>(etl::forward<UArgs>(args)), 0)...};
|
||||
@ -134,7 +134,7 @@ namespace etl
|
||||
/// \return The result of the delegate invocation.
|
||||
//*********************************************************************
|
||||
template<size_t... Indexes>
|
||||
ETL_CONSTEXPR14 TReturn execute(etl::index_sequence<Indexes...>) const ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 TReturn execute(etl::index_sequence<Indexes...>) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
return m_f(etl::get<Indexes>(m_args)...);
|
||||
}
|
||||
@ -147,7 +147,7 @@ namespace etl
|
||||
/// Base template for closure.
|
||||
//*************************************************************************
|
||||
template <typename>
|
||||
class closure;
|
||||
class closure;
|
||||
|
||||
//*************************************************************************
|
||||
/// Closure for binding one argument to a delegate and invoking it later.
|
||||
|
||||
@ -386,7 +386,7 @@ namespace etl
|
||||
template <typename TRet = TReturn>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if_t<etl::is_same<TRet, void>::value, bool>
|
||||
call_if(TParams... args) const ETL_NOEXCEPT
|
||||
call_if(TParams... args) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
if (is_valid())
|
||||
{
|
||||
@ -406,7 +406,7 @@ namespace etl
|
||||
template <typename TRet = TReturn>
|
||||
ETL_CONSTEXPR14
|
||||
typename etl::enable_if_t<!etl::is_same<TRet, void>::value, etl::optional<TReturn>>
|
||||
call_if(TParams... args) const ETL_NOEXCEPT
|
||||
call_if(TParams... args) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
etl::optional<TReturn> result;
|
||||
|
||||
@ -423,7 +423,7 @@ namespace etl
|
||||
/// Run time alternative.
|
||||
//*************************************************************************
|
||||
template <typename TAlternative>
|
||||
ETL_CONSTEXPR14 TReturn call_or(TAlternative alternative, TParams... args) const ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 TReturn call_or(TAlternative alternative, TParams... args) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
if (is_valid())
|
||||
{
|
||||
@ -440,7 +440,7 @@ namespace etl
|
||||
/// Compile time alternative.
|
||||
//*************************************************************************
|
||||
template <TReturn(*Method)(TParams...)>
|
||||
ETL_CONSTEXPR14 TReturn call_or(TParams... args) const ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 TReturn call_or(TParams... args) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
if (is_valid())
|
||||
{
|
||||
@ -583,7 +583,7 @@ namespace etl
|
||||
/// Stub call for a member function. Run time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, TReturn(T::*Method)(TParams...)>
|
||||
static ETL_CONSTEXPR14 TReturn method_stub(void* object, TParams... params) ETL_NOEXCEPT
|
||||
static ETL_CONSTEXPR14 TReturn method_stub(void* object, TParams... params) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
T* p = static_cast<T*>(object);
|
||||
return (p->*Method)(etl::forward<TParams>(params)...);
|
||||
@ -593,7 +593,7 @@ namespace etl
|
||||
/// Stub call for a const member function. Run time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, TReturn(T::*Method)(TParams...) const>
|
||||
static ETL_CONSTEXPR14 TReturn const_method_stub(void* object, TParams... params) ETL_NOEXCEPT
|
||||
static ETL_CONSTEXPR14 TReturn const_method_stub(void* object, TParams... params) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
T* const p = static_cast<T*>(object);
|
||||
return (p->*Method)(etl::forward<TParams>(params)...);
|
||||
@ -603,7 +603,7 @@ namespace etl
|
||||
/// Stub call for a member function. Compile time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, TReturn(T::*Method)(TParams...), T& Instance>
|
||||
static ETL_CONSTEXPR14 TReturn method_instance_stub(void*, TParams... params) ETL_NOEXCEPT
|
||||
static ETL_CONSTEXPR14 TReturn method_instance_stub(void*, TParams... params) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
return (Instance.*Method)(etl::forward<TParams>(params)...);
|
||||
}
|
||||
@ -612,7 +612,7 @@ namespace etl
|
||||
/// Stub call for a const member function. Compile time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, TReturn(T::*Method)(TParams...) const, const T& Instance>
|
||||
static ETL_CONSTEXPR14 TReturn const_method_instance_stub(void*, TParams... params) ETL_NOEXCEPT
|
||||
static ETL_CONSTEXPR14 TReturn const_method_instance_stub(void*, TParams... params) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
return (Instance.*Method)(etl::forward<TParams>(params)...);
|
||||
}
|
||||
@ -622,7 +622,7 @@ namespace etl
|
||||
/// Stub call for a function operator. Compile time instance.
|
||||
//*************************************************************************
|
||||
template <typename T, T& Instance>
|
||||
static ETL_CONSTEXPR14 TReturn operator_instance_stub(void*, TParams... params) ETL_NOEXCEPT
|
||||
static ETL_CONSTEXPR14 TReturn operator_instance_stub(void*, TParams... params) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
return Instance.operator()(etl::forward<TParams>(params)...);
|
||||
}
|
||||
@ -632,7 +632,7 @@ namespace etl
|
||||
/// Stub call for a free function.
|
||||
//*************************************************************************
|
||||
template <TReturn(*Method)(TParams...)>
|
||||
static ETL_CONSTEXPR14 TReturn function_stub(void*, TParams... params) ETL_NOEXCEPT
|
||||
static ETL_CONSTEXPR14 TReturn function_stub(void*, TParams... params) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
return (Method)(etl::forward<TParams>(params)...);
|
||||
}
|
||||
@ -641,7 +641,7 @@ namespace etl
|
||||
/// Stub call for a lambda or functor function.
|
||||
//*************************************************************************
|
||||
template <typename TLambda>
|
||||
static ETL_CONSTEXPR14 TReturn lambda_stub(void* object, TParams... arg) ETL_NOEXCEPT
|
||||
static ETL_CONSTEXPR14 TReturn lambda_stub(void* object, TParams... arg) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
TLambda* p = static_cast<TLambda*>(object);
|
||||
return (p->operator())(etl::forward<TParams>(arg)...);
|
||||
@ -651,7 +651,7 @@ namespace etl
|
||||
/// Stub call for a const lambda or functor function.
|
||||
//*************************************************************************
|
||||
template <typename TLambda>
|
||||
static ETL_CONSTEXPR14 TReturn const_lambda_stub(void* object, TParams... arg) ETL_NOEXCEPT
|
||||
static ETL_CONSTEXPR14 TReturn const_lambda_stub(void* object, TParams... arg) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
|
||||
{
|
||||
const TLambda* p = static_cast<const TLambda*>(object);
|
||||
return (p->operator())(etl::forward<TParams>(arg)...);
|
||||
|
||||
@ -30,6 +30,8 @@ SOFTWARE.
|
||||
|
||||
#include "etl/closure.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace
|
||||
{
|
||||
SUITE(test_closure)
|
||||
@ -39,6 +41,15 @@ namespace
|
||||
return a1 * 3;
|
||||
}
|
||||
|
||||
int f1_throwing(int)
|
||||
{
|
||||
throw std::runtime_error("throwing function");
|
||||
}
|
||||
|
||||
void f1_void(int)
|
||||
{
|
||||
}
|
||||
|
||||
int f1_ref(int& a1)
|
||||
{
|
||||
return a1 * 3;
|
||||
@ -65,6 +76,8 @@ namespace
|
||||
}
|
||||
|
||||
etl::delegate<int(int)> df1 = etl::delegate<int(int)>::create<&f1>();
|
||||
etl::delegate<int(int)> df1_throwing = etl::delegate<int(int)>::create<&f1_throwing>();
|
||||
etl::delegate<void(int)> df1_void = etl::delegate<void(int)>::create<&f1_void>();
|
||||
etl::delegate<int(int, int)> df2 = etl::delegate<int(int, int)>::create<&f2>();
|
||||
etl::delegate<int(int, int, int)> df3 = etl::delegate<int(int, int, int)>::create<&f3>();
|
||||
etl::delegate<int(int, int, int, int)> df4 = etl::delegate<int(int, int, int, int)>::create<&f4>();
|
||||
@ -99,6 +112,20 @@ namespace
|
||||
CHECK_EQUAL(16, c1_lambda());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_throwing)
|
||||
{
|
||||
etl::closure<int(int)> c1(df1_throwing, 4);
|
||||
CHECK_THROW(c1(), std::runtime_error);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_void)
|
||||
{
|
||||
etl::closure<void(int)> c1(df1_void, 4);
|
||||
c1();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_2_args)
|
||||
{
|
||||
|
||||
@ -37,6 +37,7 @@ SOFTWARE.
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -159,6 +160,20 @@ namespace
|
||||
return i + j + 1;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// The throwing function.
|
||||
//*****************************************************************************
|
||||
void throwing_void()
|
||||
{
|
||||
throw std::runtime_error("throwing function");
|
||||
}
|
||||
|
||||
int throwing_normal(int, int)
|
||||
{
|
||||
throw std::runtime_error("throwing function with two parameters");
|
||||
}
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
// The test class with member functions.
|
||||
//*****************************************************************************
|
||||
@ -358,6 +373,24 @@ namespace
|
||||
CHECK(function_called == FunctionCalled::Free_Void_Called);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_throwing)
|
||||
{
|
||||
{
|
||||
auto d = etl::delegate<void(void)>::create<throwing_void>();
|
||||
|
||||
CHECK_THROW(d(), std::runtime_error);
|
||||
CHECK_THROW(d.call_if(), std::runtime_error);
|
||||
}
|
||||
|
||||
{
|
||||
auto d = etl::delegate<int(int, int)>::create<throwing_normal>();
|
||||
|
||||
CHECK_THROW({d.call_or(alternative, VALUE1, VALUE2);}, std::runtime_error);
|
||||
CHECK_THROW({d.call_or<alternative>(VALUE1, VALUE2);}, std::runtime_error);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP17
|
||||
TEST_FIXTURE(SetupFixture, test_make_delegate_free_void)
|
||||
@ -1426,7 +1459,7 @@ namespace
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP17
|
||||
TEST_FIXTURE(SetupFixture, test_make_delegate_member_int_const_compile_tim1e_new_api)
|
||||
TEST_FIXTURE(SetupFixture, test_make_delegate_member_int_const_compile_time_new_api)
|
||||
{
|
||||
auto d = etl::make_delegate<Object, &Object::member_int_const, const_object_static>();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user