diff --git a/headers/meta.hpp/meta_base.hpp b/headers/meta.hpp/meta_base.hpp index cec6fac..116ad26 100644 --- a/headers/meta.hpp/meta_base.hpp +++ b/headers/meta.hpp/meta_base.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,10 @@ #include "meta_base/type_kinds.hpp" #include "meta_base/type_list.hpp" +#if !defined(__cpp_exceptions) +# define META_HPP_NO_EXCEPTIONS +#endif + namespace meta_hpp { using detail::select_const; @@ -57,6 +62,27 @@ namespace meta_hpp using enum_hpp::bitflags::bitflags; } +namespace meta_hpp +{ + class exception final : public std::runtime_error { + public: + explicit exception(const char* what) + : std::runtime_error(what) {} + }; + + namespace detail + { + inline void throw_exception_with [[noreturn]] (const char* what) { + #ifndef META_HPP_NO_EXCEPTIONS + throw ::meta_hpp::exception(what); + #else + (void)what; + std::abort(); + #endif + } + } +} + namespace meta_hpp { class value; diff --git a/headers/meta.hpp/meta_base/fixed_function.hpp b/headers/meta.hpp/meta_base/fixed_function.hpp index 75f8e32..ee31357 100644 --- a/headers/meta.hpp/meta_base/fixed_function.hpp +++ b/headers/meta.hpp/meta_base/fixed_function.hpp @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -60,9 +61,8 @@ namespace meta_hpp::detail } R operator()(Args... args) const { - return vtable_ - ? vtable_->call(*this, std::forward(args)...) - : throw std::bad_function_call(); + assert(vtable_ && "bad function call"); + return vtable_->call(*this, std::forward(args)...); } void reset() noexcept { diff --git a/headers/meta.hpp/meta_detail/value_utilities/arg.hpp b/headers/meta.hpp/meta_detail/value_utilities/arg.hpp index efff645..678cf88 100644 --- a/headers/meta.hpp/meta_detail/value_utilities/arg.hpp +++ b/headers/meta.hpp/meta_detail/value_utilities/arg.hpp @@ -250,7 +250,7 @@ namespace meta_hpp::detail // NOLINTNEXTLINE(readability-function-cognitive-complexity) To arg::cast() const { if ( !can_cast_to() ) { - throw std::logic_error("bad argument cast"); + throw_exception_with("bad argument cast"); } using to_raw_type_cv = std::remove_reference_t; @@ -360,6 +360,6 @@ namespace meta_hpp::detail } } - throw std::logic_error("bad argument cast"); + throw_exception_with("bad argument cast"); } } diff --git a/headers/meta.hpp/meta_detail/value_utilities/inst.hpp b/headers/meta.hpp/meta_detail/value_utilities/inst.hpp index e1dc7eb..019ff27 100644 --- a/headers/meta.hpp/meta_detail/value_utilities/inst.hpp +++ b/headers/meta.hpp/meta_detail/value_utilities/inst.hpp @@ -177,7 +177,7 @@ namespace meta_hpp::detail template < inst_class_ref_kind Q > decltype(auto) inst::cast() const { if ( !can_cast_to() ) { - throw std::logic_error("bad instance cast"); + throw_exception_with("bad instance cast"); } using inst_class_cv = std::remove_reference_t; @@ -205,6 +205,6 @@ namespace meta_hpp::detail } } - throw std::logic_error("bad instance cast"); + throw_exception_with("bad instance cast"); } } diff --git a/headers/meta.hpp/meta_states/ctor.hpp b/headers/meta.hpp/meta_states/ctor.hpp index 348d036..02fa66e 100644 --- a/headers/meta.hpp/meta_states/ctor.hpp +++ b/headers/meta.hpp/meta_states/ctor.hpp @@ -33,7 +33,7 @@ namespace meta_hpp::detail static_assert(as_object || as_raw_ptr || as_shared_ptr); if ( args.size() != ct::arity ) { - throw std::logic_error("an attempt to call a constructor with an incorrect arity"); + throw_exception_with("an attempt to call a constructor with an incorrect arity"); } return std::invoke([ @@ -41,7 +41,7 @@ namespace meta_hpp::detail // NOLINTNEXTLINE(readability-named-parameter) ](std::index_sequence) -> value { if ( !(... && (args.data() + Is)->can_cast_to>()) ) { - throw std::logic_error("an attempt to call a constructor with incorrect argument types"); + throw_exception_with("an attempt to call a constructor with incorrect argument types"); } if constexpr ( as_object ) { diff --git a/headers/meta.hpp/meta_states/dtor.hpp b/headers/meta.hpp/meta_states/dtor.hpp index a8029da..2beda6c 100644 --- a/headers/meta.hpp/meta_states/dtor.hpp +++ b/headers/meta.hpp/meta_states/dtor.hpp @@ -20,7 +20,7 @@ namespace meta_hpp::detail using class_type = typename dt::class_type; if ( !ptr.can_cast_to() ) { - throw std::logic_error("an attempt to call a destructor with an incorrect argument type"); + throw_exception_with("an attempt to call a destructor with an incorrect argument type"); } class_type* raw_ptr = ptr.cast(); diff --git a/headers/meta.hpp/meta_states/function.hpp b/headers/meta.hpp/meta_states/function.hpp index b845980..817ab3f 100644 --- a/headers/meta.hpp/meta_states/function.hpp +++ b/headers/meta.hpp/meta_states/function.hpp @@ -35,7 +35,7 @@ namespace meta_hpp::detail static_assert(as_copy || as_void || ref_as_ptr); if ( args.size() != ft::arity ) { - throw std::logic_error("an attempt to call a function with an incorrect arity"); + throw_exception_with("an attempt to call a function with an incorrect arity"); } return std::invoke([ @@ -43,7 +43,7 @@ namespace meta_hpp::detail // NOLINTNEXTLINE(readability-named-parameter) ](std::index_sequence) -> value { if ( !(... && (args.data() + Is)->can_cast_to>()) ) { - throw std::logic_error("an attempt to call a function with incorrect argument types"); + throw_exception_with("an attempt to call a function with incorrect argument types"); } if constexpr ( as_void ) { diff --git a/headers/meta.hpp/meta_states/member.hpp b/headers/meta.hpp/meta_states/member.hpp index ae208a8..3ea8518 100644 --- a/headers/meta.hpp/meta_states/member.hpp +++ b/headers/meta.hpp/meta_states/member.hpp @@ -34,7 +34,7 @@ namespace meta_hpp::detail static_assert(as_copy || as_ptr || as_ref_wrap); if ( !inst.can_cast_to() ) { - throw std::logic_error("an attempt to get a member with an incorrect instance type"); + throw_exception_with("an attempt to get a member with an incorrect instance type"); } if ( inst.is_const() ) { @@ -86,18 +86,18 @@ namespace meta_hpp::detail using value_type = typename mt::value_type; if constexpr ( std::is_const_v ) { - throw std::logic_error("an attempt to set a constant member"); + throw_exception_with("an attempt to set a constant member"); } else { if ( inst.is_const() ) { - throw std::logic_error("an attempt to set a member with an const instance type"); + throw_exception_with("an attempt to set a member with an const instance type"); } if ( !inst.can_cast_to() ) { - throw std::logic_error("an attempt to set a member with an incorrect instance type"); + throw_exception_with("an attempt to set a member with an incorrect instance type"); } if ( !arg.can_cast_to() ) { - throw std::logic_error("an attempt to set a member with an incorrect argument type"); + throw_exception_with("an attempt to set a member with an incorrect argument type"); } std::invoke(member, inst.cast()) = arg.cast(); diff --git a/headers/meta.hpp/meta_states/method.hpp b/headers/meta.hpp/meta_states/method.hpp index 96b552e..69baea2 100644 --- a/headers/meta.hpp/meta_states/method.hpp +++ b/headers/meta.hpp/meta_states/method.hpp @@ -37,11 +37,11 @@ namespace meta_hpp::detail static_assert(as_copy || as_void || ref_as_ptr); if ( args.size() != mt::arity ) { - throw std::logic_error("an attempt to call a method with an incorrect arity"); + throw_exception_with("an attempt to call a method with an incorrect arity"); } if ( !inst.can_cast_to() ) { - throw std::logic_error("an attempt to call a method with an incorrect instance type"); + throw_exception_with("an attempt to call a method with an incorrect instance type"); } return std::invoke([ @@ -49,7 +49,7 @@ namespace meta_hpp::detail // NOLINTNEXTLINE(readability-named-parameter) ](std::index_sequence) -> value { if ( !(... && (args.data() + Is)->can_cast_to>()) ) { - throw std::logic_error("an attempt to call a method with incorrect argument types"); + throw_exception_with("an attempt to call a method with incorrect argument types"); } if constexpr ( as_void ) { diff --git a/headers/meta.hpp/meta_states/variable.hpp b/headers/meta.hpp/meta_states/variable.hpp index 41f965f..54db7b7 100644 --- a/headers/meta.hpp/meta_states/variable.hpp +++ b/headers/meta.hpp/meta_states/variable.hpp @@ -52,10 +52,10 @@ namespace meta_hpp::detail using data_type = typename pt::data_type; if constexpr ( std::is_const_v ) { - throw std::logic_error("an attempt to set a constant variable"); + throw_exception_with("an attempt to set a constant variable"); } else { if ( !arg.can_cast_to() ) { - throw std::logic_error("an attempt to set a variable with an incorrect argument type"); + throw_exception_with("an attempt to set a variable with an incorrect argument type"); } *pointer = arg.cast(); } diff --git a/headers/meta.hpp/meta_value/value.hpp b/headers/meta.hpp/meta_value/value.hpp index fcd7222..b86b1b9 100644 --- a/headers/meta.hpp/meta_value/value.hpp +++ b/headers/meta.hpp/meta_value/value.hpp @@ -188,7 +188,7 @@ namespace meta_hpp if constexpr ( detail::has_deref_traits ) { return detail::deref_traits{}(v.cast()); } else { - throw std::logic_error("value type doesn't have value deref traits"); + detail::throw_exception_with("value type doesn't have value deref traits"); } }, @@ -196,7 +196,7 @@ namespace meta_hpp if constexpr ( detail::has_index_traits ) { return detail::index_traits{}(v.cast(), i); } else { - throw std::logic_error("value type doesn't have value index traits"); + detail::throw_exception_with("value type doesn't have value index traits"); } }, @@ -204,7 +204,7 @@ namespace meta_hpp if constexpr ( detail::has_less_traits ) { return detail::less_traits{}(l.cast(), r.cast()); } else { - throw std::logic_error("value type doesn't have value less traits"); + detail::throw_exception_with("value type doesn't have value less traits"); } }, @@ -212,7 +212,7 @@ namespace meta_hpp if constexpr ( detail::has_equals_traits ) { return detail::equals_traits{}(l.cast(), r.cast()); } else { - throw std::logic_error("value type doesn't have value equals traits"); + detail::throw_exception_with("value type doesn't have value equals traits"); } }, @@ -220,7 +220,7 @@ namespace meta_hpp if constexpr ( detail::has_istream_traits ) { return detail::istream_traits{}(is, v.cast()); } else { - throw std::logic_error("value type doesn't have value istream traits"); + detail::throw_exception_with("value type doesn't have value istream traits"); } }, @@ -228,7 +228,7 @@ namespace meta_hpp if constexpr ( detail::has_ostream_traits ) { return detail::ostream_traits{}(os, v.cast()); } else { - throw std::logic_error("value type doesn't have value ostream traits"); + detail::throw_exception_with("value type doesn't have value ostream traits"); } }, }; @@ -332,7 +332,7 @@ namespace meta_hpp if ( Tp* ptr = try_cast() ) { return *ptr; } - throw std::logic_error("bad value cast"); + detail::throw_exception_with("bad value cast"); } template < typename T > @@ -341,7 +341,7 @@ namespace meta_hpp if ( Tp* ptr = try_cast() ) { return std::move(*ptr); } - throw std::logic_error("bad value cast"); + detail::throw_exception_with("bad value cast"); } template < typename T > @@ -350,7 +350,7 @@ namespace meta_hpp if ( const Tp* ptr = try_cast() ) { return *ptr; } - throw std::logic_error("bad value cast"); + detail::throw_exception_with("bad value cast"); } template < typename T > @@ -359,7 +359,7 @@ namespace meta_hpp if ( const Tp* ptr = try_cast() ) { return std::move(*ptr); } - throw std::logic_error("bad value cast"); + detail::throw_exception_with("bad value cast"); } template < typename T >