more inst tests

This commit is contained in:
BlackMATov
2021-12-03 06:56:31 +07:00
parent 6f0cce9340
commit f926dbba24
3 changed files with 214 additions and 100 deletions

View File

@@ -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

View File

@@ -18,23 +18,6 @@ namespace meta_hpp::detail
struct has_value_type_less_op<T, std::void_t<decltype(
std::declval<const T&>() < std::declval<const T&>()
)>> : std::true_type {};
template < typename T >
concept has_value_type_less_op_kind = has_value_type_less_op<T>::value;
template < typename T >
concept has_not_value_type_less_op_kind = !has_value_type_less_op<T>::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<T>() < r.cast<T>();
}
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<T, std::void_t<decltype(
std::declval<const T&>() == std::declval<const T&>()
)>> : std::true_type {};
template < typename T >
concept has_value_type_equals_op_kind = has_value_type_equals_op<T>::value;
template < typename T >
concept has_not_value_type_equals_op_kind = !has_value_type_equals_op<T>::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<T>() == r.cast<T>();
}
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<T, std::void_t<decltype(
std::declval<std::istream&>() >> std::declval<T&>()
)>> : std::true_type {};
template < typename T >
concept has_value_type_istream_op_kind = has_value_type_istream_op<T>::value;
template < typename T >
concept has_not_value_type_istream_op_kind = !has_value_type_istream_op<T>::value;
template < has_value_type_istream_op_kind T >
void value_istream_function(std::istream& os, value& v) {
os >> v.cast<T>();
}
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<T, std::void_t<decltype(
std::declval<std::ostream&>() << std::declval<const T&>()
)>> : std::true_type {};
template < typename T >
concept has_value_type_ostream_op_kind = has_value_type_ostream_op<T>::value;
template < typename T >
concept has_not_value_type_ostream_op_kind = !has_value_type_ostream_op<T>::value;
template < has_value_type_ostream_op_kind T >
void value_ostream_function(std::ostream& os, const value& v) {
os << v.cast<T>();
}
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<T>(),
.type = resolve_type<T>(),
// data
+[](value& v) noexcept -> void* {
.data = +[](value& v) noexcept -> void* {
return v.try_cast<T>();
},
// cdata
+[](const value& v) noexcept -> const void* {
.cdata = +[](const value& v) noexcept -> const void* {
return v.try_cast<T>();
},
// less
&detail::value_less_function<T>,
.less = +[](const value& l, const value& r) -> bool {
if constexpr ( detail::has_value_type_less_op<T>::value ) {
return l.cast<T>() < r.cast<T>();
} else {
throw std::logic_error("value type doesn't have less operator");
}
},
// equals
&detail::value_equals_function<T>,
.equals = +[](const value& l, const value& r) -> bool {
if constexpr ( detail::has_value_type_equals_op<T>::value ) {
return l.cast<T>() == r.cast<T>();
} 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<T> ) {
dst.emplace<T>(std::move(src).cast<T>());
} 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<T> ) {
dst.emplace<T>(src.cast<T>());
} else {
@@ -180,11 +119,21 @@ namespace meta_hpp
}
},
// istream
&detail::value_istream_function<T>,
.istream = +[](std::istream& os, value& v) -> std::istream& {
if constexpr ( detail::has_value_type_istream_op<T>::value ) {
return os >> v.cast<T>();
} else {
throw std::logic_error("value type doesn't have istream operator");
}
},
// ostream
&detail::value_ostream_function<T>,
.ostream = +[](std::ostream& os, const value& v) -> std::ostream& {
if constexpr ( detail::has_value_type_ostream_op<T>::value ) {
return os << v.cast<T>();
} 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<T>())
|| (l.get_type() == resolve_type<T>() && std::less<>{}(l.cast<T>(), r));
const any_type& r_type = resolve_type<T>();
return (l.get_type() < r_type) || (l.get_type() == r_type && std::less<>{}(l.cast<T>(), r));
}
template < typename T >
bool operator<(const T& l, const value& r) {
return (resolve_type<T>() < r.get_type())
|| (resolve_type<T>() == r.get_type() && std::less<>{}(l, r.cast<T>()));
const any_type& l_type = resolve_type<T>();
return (l_type < r.get_type()) || (l_type == r.get_type() && std::less<>{}(l, r.cast<T>()));
}
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<T>() && std::equal_to<>{}(l.cast<T>(), r);
const any_type& r_type = resolve_type<T>();
return l.get_type() == r_type && std::equal_to<>{}(l.cast<T>(), r);
}
template < typename T >
bool operator==(const T& l, const value& r) {
return resolve_type<T>() == r.get_type() && std::equal_to<>{}(l, r.cast<T>());
const any_type& l_type = resolve_type<T>();
return l_type == r.get_type() && std::equal_to<>{}(l, r.cast<T>());
}
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);
}
}

View File

@@ -29,18 +29,37 @@ namespace
if ( std::is_invocable_v<decltype(method_ptr), decltype(Inst)> ) {\
CHECK(inst{Inst}.can_cast_to<clazz Qualifiers>());\
CHECK(inst_base{type_list<decltype(Inst)>{}}.can_cast_to<clazz Qualifiers>());\
CHECK_NOTHROW(inst{Inst}.cast<clazz Qualifiers>());\
\
CHECK(m_state.is_invocable_with<decltype(Inst)>());\
CHECK(m_state.invoke(Inst) == 1);\
} else {\
CHECK_FALSE(inst{Inst}.can_cast_to<clazz Qualifiers>());\
CHECK_FALSE(inst_base{type_list<decltype(Inst)>{}}.can_cast_to<clazz Qualifiers>());\
CHECK_THROWS(inst{Inst}.cast<clazz Qualifiers>());\
\
CHECK_FALSE(m_state.is_invocable_with<decltype(Inst)>());\
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<int() ToQualifiers>(&clazz::FName);\
meta::method m_state{method_state::make("", method_ptr)};\
\
if ( std::is_invocable_v<decltype(method_ptr), FromType> ) {\
CHECK(m_state.is_invocable_with<FromType>());\
CHECK(m_state.is_invocable_with(FromValue));\
CHECK(m_state.invoke(FromValue) == 1);\
} else {\
CHECK_FALSE(m_state.is_invocable_with<FromType>());\
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_<clazz>();
}
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<clazz>());
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<clazz>());
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<clazz>());
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<clazz>());
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<clazz>());
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<clazz>());
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 &&);
}
}