From f926dbba24e513261ea01ed63d98f4cd2aea0504 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 3 Dec 2021 06:56:31 +0700 Subject: [PATCH] more inst tests --- CMakeLists.txt | 1 - headers/meta.hpp/meta_utilities/value.hpp | 144 ++++++------------ untests/meta_utilities/inst_tests.cpp | 169 +++++++++++++++++++++- 3 files changed, 214 insertions(+), 100 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36bbe89..d4d87f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,6 @@ target_compile_options(${PROJECT_NAME} -Wno-ctad-maybe-unsupported -Wno-exit-time-destructors -Wno-float-equal - -Wno-ignored-qualifiers -Wno-padded -Wno-shadow-field -Wno-shadow-field-in-constructor diff --git a/headers/meta.hpp/meta_utilities/value.hpp b/headers/meta.hpp/meta_utilities/value.hpp index 4b4fedf..2f6cd54 100644 --- a/headers/meta.hpp/meta_utilities/value.hpp +++ b/headers/meta.hpp/meta_utilities/value.hpp @@ -18,23 +18,6 @@ namespace meta_hpp::detail struct has_value_type_less_op() < std::declval() )>> : std::true_type {}; - - template < typename T > - concept has_value_type_less_op_kind = has_value_type_less_op::value; - - template < typename T > - concept has_not_value_type_less_op_kind = !has_value_type_less_op::value; - - template < has_value_type_less_op_kind T > - bool value_less_function(const value& l, const value& r) { - assert(l.get_type() == r.get_type()); - return l.cast() < r.cast(); - } - - template < has_not_value_type_less_op_kind T > - bool value_less_function([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) { - throw std::logic_error("value type doesn't have less operator"); - } } namespace meta_hpp::detail @@ -46,23 +29,6 @@ namespace meta_hpp::detail struct has_value_type_equals_op() == std::declval() )>> : std::true_type {}; - - template < typename T > - concept has_value_type_equals_op_kind = has_value_type_equals_op::value; - - template < typename T > - concept has_not_value_type_equals_op_kind = !has_value_type_equals_op::value; - - template < has_value_type_equals_op_kind T > - bool value_equals_function(const value& l, const value& r) { - assert(l.get_type() == r.get_type()); - return l.cast() == r.cast(); - } - - template < has_not_value_type_equals_op_kind T > - bool value_equals_function([[maybe_unused]] const value& l, [[maybe_unused]] const value& r) { - throw std::logic_error("value type doesn't have equality operator"); - } } namespace meta_hpp::detail @@ -74,22 +40,6 @@ namespace meta_hpp::detail struct has_value_type_istream_op() >> std::declval() )>> : std::true_type {}; - - template < typename T > - concept has_value_type_istream_op_kind = has_value_type_istream_op::value; - - template < typename T > - concept has_not_value_type_istream_op_kind = !has_value_type_istream_op::value; - - template < has_value_type_istream_op_kind T > - void value_istream_function(std::istream& os, value& v) { - os >> v.cast(); - } - - template < has_not_value_type_istream_op_kind T > - void value_istream_function([[maybe_unused]] std::istream& os, [[maybe_unused]] value& v) { - throw std::logic_error("value type doesn't have istream operator"); - } } namespace meta_hpp::detail @@ -101,22 +51,6 @@ namespace meta_hpp::detail struct has_value_type_ostream_op() << std::declval() )>> : std::true_type {}; - - template < typename T > - concept has_value_type_ostream_op_kind = has_value_type_ostream_op::value; - - template < typename T > - concept has_not_value_type_ostream_op_kind = !has_value_type_ostream_op::value; - - template < has_value_type_ostream_op_kind T > - void value_ostream_function(std::ostream& os, const value& v) { - os << v.cast(); - } - - template < has_not_value_type_ostream_op_kind T > - void value_ostream_function([[maybe_unused]] std::ostream& os, [[maybe_unused]] const value& v) { - throw std::logic_error("value type doesn't have ostream operator"); - } } namespace meta_hpp @@ -133,8 +67,8 @@ namespace meta_hpp void (*const move_ctor)(std::any&, value&&); void (*const copy_ctor)(std::any&, const value&); - void (*const istream)(std::istream&, value&); - void (*const ostream)(std::ostream&, const value&); + std::istream& (*const istream)(std::istream&, value&); + std::ostream& (*const ostream)(std::ostream&, const value&); template < typename T > static const traits* get() noexcept; @@ -143,27 +77,33 @@ namespace meta_hpp template < typename T > const value::traits* value::traits::get() noexcept { static const traits traits{ - // type - resolve_type(), + .type = resolve_type(), - // data - +[](value& v) noexcept -> void* { + .data = +[](value& v) noexcept -> void* { return v.try_cast(); }, - // cdata - +[](const value& v) noexcept -> const void* { + .cdata = +[](const value& v) noexcept -> const void* { return v.try_cast(); }, - // less - &detail::value_less_function, + .less = +[](const value& l, const value& r) -> bool { + if constexpr ( detail::has_value_type_less_op::value ) { + return l.cast() < r.cast(); + } else { + throw std::logic_error("value type doesn't have less operator"); + } + }, - // equals - &detail::value_equals_function, + .equals = +[](const value& l, const value& r) -> bool { + if constexpr ( detail::has_value_type_equals_op::value ) { + return l.cast() == r.cast(); + } else { + throw std::logic_error("value type doesn't have equality operator"); + } + }, - // move_ctor - +[](std::any& dst, value&& src) { + .move_ctor = +[](std::any& dst, value&& src) { if constexpr ( std::is_move_constructible_v ) { dst.emplace(std::move(src).cast()); } else { @@ -171,8 +111,7 @@ namespace meta_hpp } }, - // copy_ctor - +[](std::any& dst, const value& src) { + .copy_ctor = +[](std::any& dst, const value& src) { if constexpr ( std::is_copy_constructible_v ) { dst.emplace(src.cast()); } else { @@ -180,11 +119,21 @@ namespace meta_hpp } }, - // istream - &detail::value_istream_function, + .istream = +[](std::istream& os, value& v) -> std::istream& { + if constexpr ( detail::has_value_type_istream_op::value ) { + return os >> v.cast(); + } else { + throw std::logic_error("value type doesn't have istream operator"); + } + }, - // ostream - &detail::value_ostream_function, + .ostream = +[](std::ostream& os, const value& v) -> std::ostream& { + if constexpr ( detail::has_value_type_ostream_op::value ) { + return os << v.cast(); + } else { + throw std::logic_error("value type doesn't have ostream operator"); + } + }, }; return &traits; } @@ -305,19 +254,18 @@ namespace meta_hpp { template < typename T > bool operator<(const value& l, const T& r) { - return (l.get_type() < resolve_type()) - || (l.get_type() == resolve_type() && std::less<>{}(l.cast(), r)); + const any_type& r_type = resolve_type(); + return (l.get_type() < r_type) || (l.get_type() == r_type && std::less<>{}(l.cast(), r)); } template < typename T > bool operator<(const T& l, const value& r) { - return (resolve_type() < r.get_type()) - || (resolve_type() == r.get_type() && std::less<>{}(l, r.cast())); + const any_type& l_type = resolve_type(); + return (l_type < r.get_type()) || (l_type == r.get_type() && std::less<>{}(l, r.cast())); } inline bool operator<(const value& l, const value& r) { - return (l.get_type() < r.get_type()) - || (l.get_type() == r.get_type() && l.traits_->less(l, r)); + return (l.get_type() < r.get_type()) || (l.get_type() == r.get_type() && l.traits_->less(l, r)); } } @@ -325,12 +273,14 @@ namespace meta_hpp { template < typename T > bool operator==(const value& l, const T& r) { - return l.get_type() == resolve_type() && std::equal_to<>{}(l.cast(), r); + const any_type& r_type = resolve_type(); + return l.get_type() == r_type && std::equal_to<>{}(l.cast(), r); } template < typename T > bool operator==(const T& l, const value& r) { - return resolve_type() == r.get_type() && std::equal_to<>{}(l, r.cast()); + const any_type& l_type = resolve_type(); + return l_type == r.get_type() && std::equal_to<>{}(l, r.cast()); } inline bool operator==(const value& l, const value& r) { @@ -341,12 +291,10 @@ namespace meta_hpp namespace meta_hpp { inline std::istream& operator>>(std::istream& is, value& v) { - v.traits_->istream(is, v); - return is; + return v.traits_->istream(is, v); } inline std::ostream& operator<<(std::ostream& os, const value& v) { - v.traits_->ostream(os, v); - return os; + return v.traits_->ostream(os, v); } } diff --git a/untests/meta_utilities/inst_tests.cpp b/untests/meta_utilities/inst_tests.cpp index dd20b2c..0549475 100644 --- a/untests/meta_utilities/inst_tests.cpp +++ b/untests/meta_utilities/inst_tests.cpp @@ -29,18 +29,37 @@ namespace if ( std::is_invocable_v ) {\ CHECK(inst{Inst}.can_cast_to());\ CHECK(inst_base{type_list{}}.can_cast_to());\ + CHECK_NOTHROW(inst{Inst}.cast());\ \ CHECK(m_state.is_invocable_with());\ CHECK(m_state.invoke(Inst) == 1);\ } else {\ CHECK_FALSE(inst{Inst}.can_cast_to());\ CHECK_FALSE(inst_base{type_list{}}.can_cast_to());\ + CHECK_THROWS(inst{Inst}.cast());\ \ CHECK_FALSE(m_state.is_invocable_with());\ CHECK_THROWS(m_state.invoke(Inst));\ }\ } +#define META_HPP_CHECK_INVOCABLE_2(FromValue, FName, FromType, ToQualifiers)\ + {\ + using namespace meta::detail;\ + auto method_ptr = meta::select(&clazz::FName);\ + meta::method m_state{method_state::make("", method_ptr)};\ + \ + if ( std::is_invocable_v ) {\ + CHECK(m_state.is_invocable_with());\ + CHECK(m_state.is_invocable_with(FromValue));\ + CHECK(m_state.invoke(FromValue) == 1);\ + } else {\ + CHECK_FALSE(m_state.is_invocable_with());\ + CHECK_FALSE(m_state.is_invocable_with(FromValue));\ + CHECK_THROWS(m_state.invoke(FromValue));\ + }\ + } + TEST_CASE("features/meta_utilities/inst2") { namespace meta = meta_hpp; @@ -48,7 +67,7 @@ TEST_CASE("features/meta_utilities/inst2") { .base_(); } -TEST_CASE("features/meta_utilities/inst2") { +TEST_CASE("features/meta_utilities/inst2/refs") { namespace meta = meta_hpp; { @@ -207,3 +226,151 @@ TEST_CASE("features/meta_utilities/inst2") { META_HPP_CHECK_INVOCABLE(CPRV2(), m6, const &&); } } + +TEST_CASE("features/meta_utilities/inst2/values") { + namespace meta = meta_hpp; + + { + // lvalue + auto LV = []() -> meta::value& { static meta::value v{clazz{}}; return v; }; + auto LV2 = []() -> meta::value& { static meta::value v{dclazz{}}; return v; }; + + meta::detail::arg a{LV()}; + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::lvalue); + + META_HPP_CHECK_INVOCABLE_2(LV(), m1, clazz&, ); + META_HPP_CHECK_INVOCABLE_2(LV(), m2, clazz&, &); + META_HPP_CHECK_INVOCABLE_2(LV(), m3, clazz&, &&); + META_HPP_CHECK_INVOCABLE_2(LV(), m4, clazz&, const); + META_HPP_CHECK_INVOCABLE_2(LV(), m5, clazz&, const &); + META_HPP_CHECK_INVOCABLE_2(LV(), m6, clazz&, const &&); + + META_HPP_CHECK_INVOCABLE_2(LV2(), m1, dclazz&, ); + META_HPP_CHECK_INVOCABLE_2(LV2(), m2, dclazz&, &); + META_HPP_CHECK_INVOCABLE_2(LV2(), m3, dclazz&, &&); + META_HPP_CHECK_INVOCABLE_2(LV2(), m4, dclazz&, const); + META_HPP_CHECK_INVOCABLE_2(LV2(), m5, dclazz&, const &); + META_HPP_CHECK_INVOCABLE_2(LV2(), m6, dclazz&, const &&); + } + + { + // const lvalue + auto CLV = []() -> const meta::value& { static meta::value v{clazz{}}; return v; }; + auto CLV2 = []() -> const meta::value& { static meta::value v{dclazz{}}; return v; }; + + meta::detail::arg a{CLV()}; + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::const_lvalue); + + META_HPP_CHECK_INVOCABLE_2(CLV(), m1, const clazz&, ); + META_HPP_CHECK_INVOCABLE_2(CLV(), m2, const clazz&, &); + META_HPP_CHECK_INVOCABLE_2(CLV(), m3, const clazz&, &&); + META_HPP_CHECK_INVOCABLE_2(CLV(), m4, const clazz&, const); + META_HPP_CHECK_INVOCABLE_2(CLV(), m5, const clazz&, const &); + META_HPP_CHECK_INVOCABLE_2(CLV(), m6, const clazz&, const &&); + + META_HPP_CHECK_INVOCABLE_2(CLV2(), m1, const dclazz&, ); + META_HPP_CHECK_INVOCABLE_2(CLV2(), m2, const dclazz&, &); + META_HPP_CHECK_INVOCABLE_2(CLV2(), m3, const dclazz&, &&); + META_HPP_CHECK_INVOCABLE_2(CLV2(), m4, const dclazz&, const); + META_HPP_CHECK_INVOCABLE_2(CLV2(), m5, const dclazz&, const &); + META_HPP_CHECK_INVOCABLE_2(CLV2(), m6, const dclazz&, const &&); + } + + { + // xvalue + auto XV = []() -> meta::value&& { static meta::value v{clazz{}}; return std::move(v); }; + auto XV2 = []() -> meta::value&& { static meta::value v{dclazz{}}; return std::move(v); }; + + meta::detail::arg a{XV()}; + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::rvalue); + + META_HPP_CHECK_INVOCABLE_2(XV(), m1, clazz&&, ); + META_HPP_CHECK_INVOCABLE_2(XV(), m2, clazz&&, &); + META_HPP_CHECK_INVOCABLE_2(XV(), m3, clazz&&, &&); + META_HPP_CHECK_INVOCABLE_2(XV(), m4, clazz&&, const); + META_HPP_CHECK_INVOCABLE_2(XV(), m5, clazz&&, const &); + META_HPP_CHECK_INVOCABLE_2(XV(), m6, clazz&&, const &&); + + META_HPP_CHECK_INVOCABLE_2(XV2(), m1, dclazz&&, ); + META_HPP_CHECK_INVOCABLE_2(XV2(), m2, dclazz&&, &); + META_HPP_CHECK_INVOCABLE_2(XV2(), m3, dclazz&&, &&); + META_HPP_CHECK_INVOCABLE_2(XV2(), m4, dclazz&&, const); + META_HPP_CHECK_INVOCABLE_2(XV2(), m5, dclazz&&, const &); + META_HPP_CHECK_INVOCABLE_2(XV2(), m6, dclazz&&, const &&); + } + + { + // const xvalue + auto CXV = []() -> const meta::value&& { static meta::value v{clazz{}}; return std::move(v); }; + auto CXV2 = []() -> const meta::value&& { static meta::value v{dclazz{}}; return std::move(v); }; + + meta::detail::arg a{CXV()}; + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::const_rvalue); + + META_HPP_CHECK_INVOCABLE_2(CXV(), m1, const clazz&&, ); + META_HPP_CHECK_INVOCABLE_2(CXV(), m2, const clazz&&, &); + META_HPP_CHECK_INVOCABLE_2(CXV(), m3, const clazz&&, &&); + META_HPP_CHECK_INVOCABLE_2(CXV(), m4, const clazz&&, const); + META_HPP_CHECK_INVOCABLE_2(CXV(), m5, const clazz&&, const &); + META_HPP_CHECK_INVOCABLE_2(CXV(), m6, const clazz&&, const &&); + + META_HPP_CHECK_INVOCABLE_2(CXV2(), m1, const dclazz&&, ); + META_HPP_CHECK_INVOCABLE_2(CXV2(), m2, const dclazz&&, &); + META_HPP_CHECK_INVOCABLE_2(CXV2(), m3, const dclazz&&, &&); + META_HPP_CHECK_INVOCABLE_2(CXV2(), m4, const dclazz&&, const); + META_HPP_CHECK_INVOCABLE_2(CXV2(), m5, const dclazz&&, const &); + META_HPP_CHECK_INVOCABLE_2(CXV2(), m6, const dclazz&&, const &&); + } + + { + // prvalue + auto PRV = []() -> meta::value { return meta::value{clazz{}}; }; + auto PRV2 = []() -> meta::value { return meta::value{dclazz{}}; }; + + meta::detail::arg a{PRV()}; + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::rvalue); + + META_HPP_CHECK_INVOCABLE_2(PRV(), m1, clazz, ); + META_HPP_CHECK_INVOCABLE_2(PRV(), m2, clazz, &); + META_HPP_CHECK_INVOCABLE_2(PRV(), m3, clazz, &&); + META_HPP_CHECK_INVOCABLE_2(PRV(), m4, clazz, const); + META_HPP_CHECK_INVOCABLE_2(PRV(), m5, clazz, const &); + META_HPP_CHECK_INVOCABLE_2(PRV(), m6, clazz, const &&); + + META_HPP_CHECK_INVOCABLE_2(PRV2(), m1, dclazz, ); + META_HPP_CHECK_INVOCABLE_2(PRV2(), m2, dclazz, &); + META_HPP_CHECK_INVOCABLE_2(PRV2(), m3, dclazz, &&); + META_HPP_CHECK_INVOCABLE_2(PRV2(), m4, dclazz, const); + META_HPP_CHECK_INVOCABLE_2(PRV2(), m5, dclazz, const &); + META_HPP_CHECK_INVOCABLE_2(PRV2(), m6, dclazz, const &&); + } + + { + // const prvalue + auto CPRV = []() -> const meta::value { return meta::value{clazz{}}; }; + auto CPRV2 = []() -> const meta::value { return meta::value{dclazz{}}; }; + + meta::detail::arg a{CPRV()}; + CHECK(a.get_raw_type() == meta::resolve_type()); + CHECK(a.get_ref_type() == meta::detail::arg::ref_types::const_rvalue); + + META_HPP_CHECK_INVOCABLE_2(CPRV(), m1, const clazz, ); + META_HPP_CHECK_INVOCABLE_2(CPRV(), m2, const clazz, &); + META_HPP_CHECK_INVOCABLE_2(CPRV(), m3, const clazz, &&); + META_HPP_CHECK_INVOCABLE_2(CPRV(), m4, const clazz, const); + META_HPP_CHECK_INVOCABLE_2(CPRV(), m5, const clazz, const &); + META_HPP_CHECK_INVOCABLE_2(CPRV(), m6, const clazz, const &&); + + META_HPP_CHECK_INVOCABLE_2(CPRV2(), m1, const dclazz, ); + META_HPP_CHECK_INVOCABLE_2(CPRV2(), m2, const dclazz, &); + META_HPP_CHECK_INVOCABLE_2(CPRV2(), m3, const dclazz, &&); + META_HPP_CHECK_INVOCABLE_2(CPRV2(), m4, const dclazz, const); + META_HPP_CHECK_INVOCABLE_2(CPRV2(), m5, const dclazz, const &); + META_HPP_CHECK_INVOCABLE_2(CPRV2(), m6, const dclazz, const &&); + } +}