diff --git a/appveyor.yml b/appveyor.yml index a5528862..5a4fe67e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,9 @@ version: 6.1.x.{build} image: - - Visual Studio 2017 + - Visual Studio 2019 environment: matrix: - - VS_VERSION: "Visual Studio 15" + - VS_VERSION: "Visual Studio 16" build_script: - cmd: >- mkdir build diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index d5eb774a..30b8ce18 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -271,7 +271,7 @@ namespace chaiscript { template - [[nodiscard]] auto make_vector(T && ... t) + [[nodiscard]] auto make_vector(T &&... t) -> std::vector...>> { using container_type = std::vector...>>; diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index d133dbff..deba0bc7 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -185,7 +185,9 @@ namespace chaiscript return const_var(c_lhs * c_rhs); case Operators::Opers::difference: return const_var(c_lhs - c_rhs); - } + default: + break; + } if constexpr (!std::is_floating_point::value && !std::is_floating_point::value) { @@ -203,7 +205,9 @@ namespace chaiscript return const_var(c_lhs | c_rhs); case Operators::Opers::bitwise_xor: return const_var(c_lhs ^ c_rhs); - } + default: + break; + } } if (t_lhs) { @@ -224,7 +228,9 @@ namespace chaiscript case Operators::Opers::assign_difference: *t_lhs -= c_rhs; return t_bv; - } + default: + break; + } if constexpr (!std::is_floating_point::value && !std::is_floating_point::value) { switch (t_oper) { @@ -247,7 +253,9 @@ namespace chaiscript case Operators::Opers::assign_bitwise_xor: *t_lhs ^= c_rhs; return t_bv; - } + default: + break; + } } } @@ -299,7 +307,9 @@ namespace chaiscript case Operators::Opers::pre_decrement: --(*lhs); return t_lhs; - } + default: + break; + } } switch (t_oper) { @@ -307,13 +317,17 @@ namespace chaiscript return const_var(-c_lhs); case Operators::Opers::unary_plus: return const_var(+c_lhs); - } + default: + break; + } if constexpr (!std::is_floating_point_v>) { switch (t_oper) { case Operators::Opers::bitwise_complement: return const_var(~c_lhs); - } + default: + break; + } } throw chaiscript::detail::exception::bad_any_cast(); diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 3fcb38cd..c249f317 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1303,8 +1303,8 @@ namespace chaiscript const auto lhssize = lhsparamtypes.size(); const auto rhssize = rhsparamtypes.size(); - constexpr const auto boxed_type = user_type(); - constexpr const auto boxed_pod_type = user_type(); + const auto boxed_type = user_type(); + const auto boxed_pod_type = user_type(); for (size_t i = 1; i < lhssize && i < rhssize; ++i) { diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index 6071898b..92e51d3b 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -39,7 +39,7 @@ namespace chaiscript { } - Ret call(const Function_Params ¶ms, const Type_Conversions_State &t_state) + Ret call(const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_state) { if constexpr (std::is_arithmetic_v) { return Boxed_Number(dispatch::dispatch(m_funcs, params, t_state)).get_as(); @@ -57,11 +57,11 @@ namespace chaiscript if (m_conversions) { Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves()); - return call(Function_Params{params}, state); + return call(chaiscript::Function_Params{params}, state); } else { Type_Conversions conv; Type_Conversions_State state(conv, conv.conversion_saves()); - return call(Function_Params{params}, state); + return call(chaiscript::Function_Params{params}, state); } } diff --git a/include/chaiscript/dispatchkit/function_params.hpp b/include/chaiscript/dispatchkit/function_params.hpp index 090f7004..1430becc 100644 --- a/include/chaiscript/dispatchkit/function_params.hpp +++ b/include/chaiscript/dispatchkit/function_params.hpp @@ -30,13 +30,13 @@ namespace chaiscript { } explicit Function_Params(const std::vector &vec) - : m_begin(&vec.front()), m_end(&vec.front() + vec.size()) + : m_begin(vec.empty() ? nullptr : &vec.front()), m_end(vec.empty() ? nullptr : &vec.front() + vec.size()) { } template constexpr explicit Function_Params(const std::array &a) - : m_begin(std::begin(a)), m_end(std::end(a)) + : m_begin(&a.front()), m_end(&a.front() + Size) { } @@ -74,6 +74,13 @@ namespace chaiscript { }; + // Constructor specialization for array of size 0 + template<> + constexpr Function_Params::Function_Params(const std::array & /* a */) + : m_begin(nullptr), m_end(nullptr) + { + } + } diff --git a/include/chaiscript/dispatchkit/function_signature.hpp b/include/chaiscript/dispatchkit/function_signature.hpp index 11c780a4..7c351ec2 100644 --- a/include/chaiscript/dispatchkit/function_signature.hpp +++ b/include/chaiscript/dispatchkit/function_signature.hpp @@ -4,121 +4,142 @@ #include namespace chaiscript::dispatch::detail { - template - struct Function_Params - { - }; - template - struct Function_Signature { - using Param_Types = Params; - using Return_Type = Ret; - constexpr static const bool is_object = IsObject; - constexpr static const bool is_member_object = IsMemberObject; - constexpr static const bool is_noexcept = IsNoExcept; - template - constexpr Function_Signature(T &&) noexcept {} - constexpr Function_Signature() noexcept = default; - }; +template +struct Function_Params +{ +}; - // Free functions +template +struct Function_Signature +{ + using Param_Types = Params; + using Return_Type = Ret; + constexpr static const bool is_object = IsObject; + constexpr static const bool is_member_object = IsMemberObject; + constexpr static const bool is_noexcept = IsNoExcept; + template + constexpr Function_Signature(T &&) noexcept {} + constexpr Function_Signature() noexcept = default; +}; - template - Function_Signature(Ret (*f)(Param...)) -> Function_Signature>; +// Free functions - template - Function_Signature(Ret (*f)(Param...) noexcept) -> Function_Signature, true>; +template +Function_Signature(Ret (*f)(Param...))->Function_Signature>; - // no reference specifier +template +Function_Signature(Ret (*f)(Param...) noexcept)->Function_Signature, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) volatile) -> Function_Signature, false, true>; +// no reference specifier - template - Function_Signature(Ret (Class::*f)(Param ...) volatile noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile)->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) volatile const) -> Function_Signature, false, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) volatile const noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile const)->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) ) -> Function_Signature, false, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile const noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...))->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) const) -> Function_Signature, false, true>; +template +Function_Signature(Ret (Class::*f)(Param...) noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) const noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) const)->Function_Signature, false, true>; - // & reference specifier +template +Function_Signature(Ret (Class::*f)(Param...) const noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) volatile &) -> Function_Signature, false, true>; +// & reference specifier - template - Function_Signature(Ret (Class::*f)(Param ...) volatile & noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile &)->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) volatile const &) -> Function_Signature, false, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile &noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) volatile const & noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile const &)->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) & ) -> Function_Signature, false, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile const &noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) & noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) &)->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) const &) -> Function_Signature, false, true>; +template +Function_Signature(Ret (Class::*f)(Param...) & noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) const & noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) const &)->Function_Signature, false, true>; - // && reference specifier +template +Function_Signature(Ret (Class::*f)(Param...) const &noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) volatile &&) -> Function_Signature, false, true>; +// && reference specifier - template - Function_Signature(Ret (Class::*f)(Param ...) volatile && noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile &&)->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) volatile const &&) -> Function_Signature, false, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile &&noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) volatile const && noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile const &&)->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) &&) -> Function_Signature, false, true>; +template +Function_Signature(Ret (Class::*f)(Param...) volatile const &&noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) && noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) &&)->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) const &&) -> Function_Signature, false, true>; +template +Function_Signature(Ret (Class::*f)(Param...) && noexcept)->Function_Signature, true, true>; - template - Function_Signature(Ret (Class::*f)(Param ...) const && noexcept) -> Function_Signature, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) const &&)->Function_Signature, false, true>; - template - Function_Signature(Ret (Class::*f)) -> Function_Signature, true, true, true>; +template +Function_Signature(Ret (Class::*f)(Param...) const &&noexcept)->Function_Signature, true, true>; - template - Function_Signature(Func &&) -> Function_Signature< - typename decltype(Function_Signature{&std::decay_t::operator()})::Return_Type, - typename decltype(Function_Signature{&std::decay_t::operator()})::Param_Types, - decltype(Function_Signature{&std::decay_t::operator()})::is_noexcept, - false, - false, - true - >; +template +Function_Signature(Ret(Class::*f))->Function_Signature, true, true, true>; + +// primary template handles types that have no nested ::type member: +template> +struct has_call_operator : std::false_type +{ +}; + +// specialization recognizes types that do have a nested ::type member: +template +struct has_call_operator> : std::true_type +{ +}; + +template +auto function_signature(const Func &f) +{ + if constexpr (has_call_operator::value) { + return Function_Signature< + typename decltype(Function_Signature{ &std::decay_t::operator() })::Return_Type, + typename decltype(Function_Signature{ &std::decay_t::operator() })::Param_Types, + decltype(Function_Signature{ &std::decay_t::operator() })::is_noexcept, + false, + false, + true>{}; + } else { + return Function_Signature{ f }; + } } +}// namespace chaiscript::dispatch::detail + #endif diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index d3c751ee..00b81f43 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -77,7 +77,7 @@ namespace chaiscript std::vector convert(Function_Params t_params, const Type_Conversions_State &t_conversions) const { auto vals = t_params.to_vector(); - constexpr auto dynamic_object_type_info = user_type(); + const auto dynamic_object_type_info = user_type(); for (size_t i = 0; i < vals.size(); ++i) { const auto &name = m_types[i].first; @@ -117,7 +117,7 @@ namespace chaiscript // second result: needs conversions std::pair match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept { - constexpr auto dynamic_object_type_info = user_type(); + const auto dynamic_object_type_info = user_type(); bool needs_conversion = false; if (!m_has_types) { return std::make_pair(true, needs_conversion); } @@ -252,9 +252,9 @@ namespace chaiscript static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions) noexcept { - constexpr auto boxed_value_ti = user_type(); - constexpr auto boxed_number_ti = user_type(); - constexpr auto function_ti = user_type>(); + const auto boxed_value_ti = user_type(); + const auto boxed_number_ti = user_type(); + const auto function_ti = user_type>(); if (ti.is_undef() || ti.bare_equal(boxed_value_ti) @@ -757,7 +757,7 @@ namespace chaiscript { return false; } - constexpr auto class_type_info = user_type(); + const auto class_type_info = user_type(); return vals[0].get_type_info().bare_equal(class_type_info); } @@ -844,7 +844,7 @@ namespace chaiscript namespace detail { template - bool types_match_except_for_arithmetic(const FuncType &t_func, const Function_Params &plist, + bool types_match_except_for_arithmetic(const FuncType &t_func, const chaiscript::Function_Params &plist, const Type_Conversions_State &t_conversions) noexcept { const std::vector &types = t_func->get_param_types(); @@ -863,7 +863,7 @@ namespace chaiscript } template - Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const Function_Params &plist, + Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const chaiscript::Function_Params &plist, const Type_Conversions_State &t_conversions, const Funcs &t_funcs) { InItr matching_func(end); @@ -919,7 +919,7 @@ namespace chaiscript ); try { - return (*(matching_func->second))(Function_Params{newplist}, t_conversions); + return (*(matching_func->second))(chaiscript::Function_Params{newplist}, t_conversions); } catch (const exception::bad_boxed_cast &) { //parameter failed to cast } catch (const exception::arity_error &) { diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 3b8a99bd..d4f7cb9e 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -78,7 +78,7 @@ namespace chaiscript */ template bool compare_types_cast(Ret (*)(Params...), - const Function_Params ¶ms, const Type_Conversions_State &t_conversions) noexcept + const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) noexcept { try { std::vector::size_type i = 0; @@ -93,7 +93,7 @@ namespace chaiscript template Ret call_func(Ret (*)(Params...), std::index_sequence, const Callable &f, - [[maybe_unused]] const Function_Params ¶ms, + [[maybe_unused]] const chaiscript::Function_Params ¶ms, [[maybe_unused]] const Type_Conversions_State &t_conversions) { return f(boxed_cast(params[I], &t_conversions)...); @@ -106,7 +106,7 @@ namespace chaiscript /// the bad_boxed_cast is passed up to the caller. template Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f, - const Function_Params ¶ms, const Type_Conversions_State &t_conversions) + const chaiscript::Function_Params ¶ms, const Type_Conversions_State &t_conversions) { if constexpr (std::is_same_v) { call_func(sig, std::index_sequence_for{}, f, params, t_conversions); diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 907b0035..1faf59f6 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -34,7 +34,8 @@ namespace chaiscript // we now that the Param pack will have only one element, so we are safe expanding it here return Proxy_Function(chaiscript::make_shared...>>(std::forward(func))); } else if constexpr (Is_Member) { - auto call = [func = std::forward(func)](auto && obj, auto && ... param) noexcept(Is_Noexcept) -> decltype(auto) { + // TODO some kind of bug is preventing forwarding of this noexcept for the lambda + auto call = [func = std::forward(func)](auto && obj, auto && ... param) /* noexcept(Is_Noexcept) */ -> decltype(auto) { return (( get_first_param(Function_Params{}, obj).*func )(std::forward(param)...)); }; return Proxy_Function( @@ -87,7 +88,7 @@ namespace chaiscript template Proxy_Function fun(T &&t) { - return dispatch::detail::make_callable(std::forward(t), dispatch::detail::Function_Signature{t}); + return dispatch::detail::make_callable(std::forward(t), dispatch::detail::function_signature(t)); } diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 9d07ddaa..c98cb8cb 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -388,7 +388,7 @@ namespace chaiscript template bool convertable_type() const noexcept { - constexpr auto type = user_type().bare_type_info(); + const auto type = user_type().bare_type_info(); return thread_cache().count(type) != 0; } diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 76c31bc8..365386ad 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -713,15 +713,8 @@ TEST_CASE("Object copy counts") CHECK(Object_Copy_Count_Test::copycount() == 0); CHECK(Object_Copy_Count_Test::constructcount() == 1); - - -#ifdef CHAISCRIPT_MSVC - CHECK(Object_Copy_Count_Test::destructcount() == 3); - CHECK(Object_Copy_Count_Test::movecount() == 2); -#else CHECK(Object_Copy_Count_Test::destructcount() == 2); CHECK(Object_Copy_Count_Test::movecount() == 1); -#endif }