diff --git a/headers/meta.hpp/meta.hpp b/headers/meta.hpp/meta.hpp index 125d059..eb2532c 100644 --- a/headers/meta.hpp/meta.hpp +++ b/headers/meta.hpp/meta.hpp @@ -17,6 +17,9 @@ #include "meta_class.hpp" #include "meta_class_info.hpp" +#include "meta_ctor.hpp" +#include "meta_ctor_info.hpp" + #include "meta_data.hpp" #include "meta_data_info.hpp" diff --git a/headers/meta.hpp/meta_class.hpp b/headers/meta.hpp/meta_class.hpp index 2912fb1..545acff 100644 --- a/headers/meta.hpp/meta_class.hpp +++ b/headers/meta.hpp/meta_class.hpp @@ -8,6 +8,7 @@ #include "meta_fwd.hpp" +#include "meta_ctor.hpp" #include "meta_data.hpp" #include "meta_field.hpp" #include "meta_function.hpp" @@ -40,6 +41,12 @@ namespace meta_hpp detail::merge_with(info_.classes_, info.id(), info, &class_info::merge); } + template < typename... Args > + void add_(ctor_ internal) { + ctor_info info = std::move(internal).template make_info(); + detail::merge_with(info_.ctors_, info.family(), info, &ctor_info::merge); + } + void add_(data_ internal) { data_info info = std::move(internal).make_info(); detail::merge_with(info_.datas_, info.id(), info, &data_info::merge); diff --git a/headers/meta.hpp/meta_class_info.hpp b/headers/meta.hpp/meta_class_info.hpp index 74a63ee..afe0277 100644 --- a/headers/meta.hpp/meta_class_info.hpp +++ b/headers/meta.hpp/meta_class_info.hpp @@ -9,6 +9,7 @@ #include "meta_fwd.hpp" #include "meta_value.hpp" +#include "meta_ctor_info.hpp" #include "meta_data_info.hpp" #include "meta_field_info.hpp" #include "meta_function_info.hpp" @@ -42,6 +43,13 @@ namespace meta_hpp } } + template < typename F > + void each_ctor(F&& f) const { + for ( auto&& family_info : ctors_ ) { + std::invoke(f, family_info.second); + } + } + template < typename F > void each_data(F&& f) const { for ( auto&& id_info : datas_ ) { @@ -80,6 +88,7 @@ namespace meta_hpp template < typename F > void visit(F&& f) const { each_class(f); + each_ctor(f); each_data(f); each_field(f); each_function(f); @@ -91,6 +100,16 @@ namespace meta_hpp return detail::find_opt(classes_, id); } + template < typename... Args > + std::optional get_ctor() const { + for ( auto&& family_info : ctors_ ) { + if ( family_info.second.is_invocable() ) { + return family_info.second; + } + } + return std::nullopt; + } + std::optional get_data(std::string_view id) const { return detail::find_opt(datas_, id); } @@ -116,6 +135,7 @@ namespace meta_hpp throw std::logic_error("class_info::merge failed"); } detail::merge_with(classes_, other.classes_, &class_info::merge); + detail::merge_with(ctors_, other.ctors_, &ctor_info::merge); detail::merge_with(datas_, other.datas_, &data_info::merge); detail::merge_with(fields_, other.fields_, &field_info::merge); detail::merge_with(functions_, other.functions_, &function_info::merge); @@ -134,6 +154,7 @@ namespace meta_hpp std::string id_; family_id family_; std::map> classes_; + std::map> ctors_; std::map> datas_; std::map> fields_; std::map> functions_; diff --git a/headers/meta.hpp/meta_ctor.hpp b/headers/meta.hpp/meta_ctor.hpp new file mode 100644 index 0000000..d338ced --- /dev/null +++ b/headers/meta.hpp/meta_ctor.hpp @@ -0,0 +1,43 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "meta_fwd.hpp" + +#include "meta_data.hpp" + +#include "meta_ctor_info.hpp" + +namespace meta_hpp +{ + template < typename... Args > + class ctor_ { + public: + ctor_() = default; + + template < typename Class > + ctor_info make_info() const { + static_assert(std::is_constructible_v); + ctor_info info{detail::typename_arg, detail::typename_args}; + detail::merge_with(info.datas_, datas_, &data_info::merge); + return info; + } + + template < typename... Internals > + ctor_& operator()(Internals&&...internals) { + (add_(std::forward(internals)), ...); + return *this; + } + private: + void add_(data_ internal) { + data_info info = std::move(internal).make_info(); + detail::merge_with(datas_, info.id(), info, &data_info::merge); + } + private: + std::map> datas_; + }; +} diff --git a/headers/meta.hpp/meta_ctor_info.hpp b/headers/meta.hpp/meta_ctor_info.hpp new file mode 100644 index 0000000..b646da7 --- /dev/null +++ b/headers/meta.hpp/meta_ctor_info.hpp @@ -0,0 +1,188 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "meta_fwd.hpp" + +#include "meta_value.hpp" + +#include "meta_data_info.hpp" + +namespace meta_hpp::ctor_detail +{ + template < typename Class, typename... Args, std::size_t... Is > + value raw_invoke_impl( + value* args, + std::index_sequence) + { + using ct = detail::ctor_traits; + using return_type = typename ct::return_type; + using argument_types = typename ct::argument_types; + + [[maybe_unused]] auto typed_arguments = std::make_tuple( + (args + Is)->try_cast>()...); + + if ( !(std::get(typed_arguments) && ...) ) { + throw std::logic_error("an attempt to call a ctor with incorrect argument types"); + } + + return_type return_value{std::move(*std::get(typed_arguments))...}; + return value{std::move(return_value)}; + } + + template < typename Class, typename... Args > + value raw_invoke( + value* args, + std::size_t arg_count) + { + using ct = detail::ctor_traits; + + if ( arg_count != ct::arity ) { + throw std::logic_error("an attempt to call a ctor with an incorrect arity"); + } + + return raw_invoke_impl(args, std::make_index_sequence()); + } + + using ctor_invoke = std::function; + + template < typename Class, typename... Args > + ctor_invoke make_invoke() { + using namespace std::placeholders; + return std::bind(&raw_invoke, _1, _2); + } + + template < typename Class, typename... Args > + family_id make_return_type() { + using ct = detail::ctor_traits; + using return_type = typename ct::return_type; + return get_family_id(); + } + + template < typename Class, typename... Args, std::size_t... Is > + std::vector make_argument_types_impl(std::index_sequence) { + using ct = detail::ctor_traits; + using argument_types = typename ct::argument_types; + return { get_family_id>()... }; + } + + template < typename Class, typename... Args > + std::vector make_argument_types() { + using ct = detail::ctor_traits; + return make_argument_types_impl(std::make_index_sequence()); + } + + template < typename... Args, std::size_t... Is > + bool parameters_equal(const std::vector& parameters, std::index_sequence) { + if ( parameters.size() != sizeof...(Args) ) { + return false; + } + return ((get_family_id>>() == parameters[Is]) && ... ); + } + + template < typename... Args > + bool parameters_equal(const std::vector& parameters) { + return parameters_equal(parameters, std::make_index_sequence()); + } +} + +namespace meta_hpp +{ + class ctor_info { + public: + ctor_info() = delete; + + ctor_info(ctor_info&&) = default; + ctor_info(const ctor_info&) = default; + + ctor_info& operator=(ctor_info&&) = default; + ctor_info& operator=(const ctor_info&) = default; + public: + family_id family() const noexcept { + return family_; + } + + std::size_t arity() const noexcept { + return argument_types_.size(); + } + + family_id return_type() const noexcept { + return return_type_; + } + + std::optional argument_type(std::size_t index) const noexcept { + if ( index < argument_types_.size() ) { + return argument_types_[index]; + } + return std::nullopt; + } + + template < typename... Args > + value invoke(Args&&... args) const { + if constexpr ( sizeof...(Args) > 0u ) { + std::array vargs{std::forward(args)...}; + return invoke_(vargs.data(), vargs.size()); + } else { + return invoke_(nullptr, 0u); + } + } + + template < typename R, typename Rp = std::decay_t, typename... Args > + Rp invoke_r(Args&&... args) const { + return invoke(std::forward(args)...).template cast(); + } + + template < typename... Args > + value operator()(Args&&... args) const { + return invoke(std::forward(args)...); + } + + template < typename... Args > + bool is_invocable() const noexcept { + return ctor_detail::parameters_equal(argument_types_); + } + + template < typename F > + void each_data(F&& f) const { + for ( auto&& id_info : datas_ ) { + std::invoke(f, id_info.second); + } + } + + template < typename F > + void visit(F&& f) const { + each_data(f); + } + + std::optional get_data(std::string_view id) const { + return detail::find_opt(datas_, id); + } + + void merge(const ctor_info& other) { + if ( family() != other.family() ) { + throw std::logic_error("ctor_info::merge failed"); + } + detail::merge_with(datas_, other.datas_, &data_info::merge); + } + private: + template < typename... Args > + friend class ctor_; + + template < typename Class, typename... Args > + ctor_info(detail::typename_arg_t, detail::typename_args_t) + : family_{get_family_id>()} + , return_type_{ctor_detail::make_return_type()} + , argument_types_{ctor_detail::make_argument_types()} + , invoke_{ctor_detail::make_invoke()} {} + private: + family_id family_; + family_id return_type_; + std::vector argument_types_; + ctor_detail::ctor_invoke invoke_; + std::map> datas_; + }; +} diff --git a/headers/meta.hpp/meta_field_info.hpp b/headers/meta.hpp/meta_field_info.hpp index a69ba00..4241694 100644 --- a/headers/meta.hpp/meta_field_info.hpp +++ b/headers/meta.hpp/meta_field_info.hpp @@ -122,9 +122,23 @@ namespace meta_hpp return getter_(instance); } + template < typename R, typename Rp = std::decay_t > + Rp get_r(cinstance instance) const { + return get(instance).template cast(); + } + template < typename Value > void set(instance instance, Value&& value) const { - return setter_(instance, std::forward(value)); + setter_(instance, std::forward(value)); + } + + value operator()(cinstance instance) const { + return get(instance); + } + + template < typename Value > + void operator()(instance instance, Value&& value) const { + set(instance, std::forward(value)); } template < typename F > diff --git a/headers/meta.hpp/meta_function_info.hpp b/headers/meta.hpp/meta_function_info.hpp index 30c10f9..4ae51cd 100644 --- a/headers/meta.hpp/meta_function_info.hpp +++ b/headers/meta.hpp/meta_function_info.hpp @@ -134,6 +134,19 @@ namespace meta_hpp } } + template < typename R, typename Rp = std::decay_t, typename... Args > + std::optional invoke_r(Args&&... args) const { + if ( std::optional r = invoke(std::forward(args)...) ) { + return std::move(r)->template cast(); + } + return std::nullopt; + } + + template < typename... Args > + std::optional operator()(Args&&... args) const { + return invoke(std::forward(args)...); + } + template < typename F > void each_data(F&& f) const { for ( auto&& id_info : datas_ ) { diff --git a/headers/meta.hpp/meta_fwd.hpp b/headers/meta.hpp/meta_fwd.hpp index e23d02e..65773b2 100644 --- a/headers/meta.hpp/meta_fwd.hpp +++ b/headers/meta.hpp/meta_fwd.hpp @@ -105,8 +105,15 @@ namespace meta_hpp::detail struct typename_arg_t { }; + template < typename... Args > + struct typename_args_t { + }; + template < typename Arg > inline typename_arg_t typename_arg; + + template < typename... Args > + inline typename_args_t typename_args; } namespace meta_hpp::detail @@ -136,6 +143,16 @@ namespace meta_hpp::detail } } +namespace meta_hpp::detail +{ + template < typename Class, typename... Args > + struct ctor_traits { + static constexpr std::size_t arity = sizeof...(Args); + using return_type = std::decay_t; + using argument_types = std::tuple...>; + }; +} + namespace meta_hpp::detail { template < typename Field > diff --git a/headers/meta.hpp/meta_instance.hpp b/headers/meta.hpp/meta_instance.hpp index cd8e5b2..229bc03 100644 --- a/headers/meta.hpp/meta_instance.hpp +++ b/headers/meta.hpp/meta_instance.hpp @@ -56,7 +56,7 @@ namespace meta_hpp std::add_pointer_t try_cast() noexcept { static_assert(!std::is_reference_v); - return fid() == get_family_id() + return fid_ == get_family_id() ? static_cast>(data_) : nullptr; } @@ -65,7 +65,7 @@ namespace meta_hpp std::add_pointer_t> try_cast() const noexcept { static_assert(!std::is_reference_v); - return fid() == get_family_id() + return fid_ == get_family_id() ? static_cast>>(data_) : nullptr; } @@ -91,8 +91,8 @@ namespace meta_hpp , typename = std::enable_if_t> , typename = std::enable_if_t> , typename = std::enable_if_t> > - cinstance(const T& data) - : data_{std::addressof(data)} + cinstance(const T& v) + : data_{std::addressof(v)} , fid_{get_family_id()} {} cinstance(const value& v) @@ -115,7 +115,7 @@ namespace meta_hpp std::add_pointer_t> try_cast() const noexcept { static_assert(!std::is_reference_v); - return fid() == get_family_id() + return fid_ == get_family_id() ? static_cast>>(data_) : nullptr; } diff --git a/headers/meta.hpp/meta_method_info.hpp b/headers/meta.hpp/meta_method_info.hpp index 8c5167e..c6a13b0 100644 --- a/headers/meta.hpp/meta_method_info.hpp +++ b/headers/meta.hpp/meta_method_info.hpp @@ -208,20 +208,31 @@ namespace meta_hpp std::optional invoke(T& inst, Args&&... args) const { if constexpr ( sizeof...(Args) > 0u ) { std::array vargs{std::forward(args)...}; - return invoke_(inst, vargs.data(), vargs.size()); + if constexpr ( std::is_const_v ) { + return cinvoke_(inst, vargs.data(), vargs.size()); + } else { + return invoke_(inst, vargs.data(), vargs.size()); + } } else { - return invoke_(inst, nullptr, 0u); + if constexpr ( std::is_const_v ) { + return cinvoke_(inst, nullptr, 0u); + } else { + return invoke_(inst, nullptr, 0u); + } } } - template < typename T, typename... Args > - std::optional invoke(const T& inst, Args&&... args) const { - if constexpr ( sizeof...(Args) > 0u ) { - std::array vargs{std::forward(args)...}; - return cinvoke_(inst, vargs.data(), vargs.size()); - } else { - return cinvoke_(inst, nullptr, 0u); + template < typename R, typename Rp = std::decay_t, typename T, typename... Args > + std::optional invoke_r(T& inst, Args&&... args) const { + if ( std::optional r = invoke(inst, std::forward(args)...) ) { + return std::move(r)->template cast(); } + return std::nullopt; + } + + template < typename T, typename... Args > + std::optional operator()(T& inst, Args&&... args) const { + return invoke(inst, std::forward(args)...); } template < typename F > diff --git a/headers/meta.hpp/meta_registry.hpp b/headers/meta.hpp/meta_registry.hpp index 5b9f41b..450c0e3 100644 --- a/headers/meta.hpp/meta_registry.hpp +++ b/headers/meta.hpp/meta_registry.hpp @@ -11,6 +11,8 @@ #include "meta_type.hpp" #include "meta_class.hpp" +#include "meta_ctor.hpp" +#include "meta_data.hpp" #include "meta_field.hpp" #include "meta_function.hpp" #include "meta_method.hpp" @@ -150,6 +152,7 @@ namespace meta_hpp detail::merge_with(classes_, name, info, &class_info::merge); info.visit(overloaded { + [](const ctor_info&) {}, [](const data_info&) {}, [this, &name](const auto& internal){ add_(name, internal); diff --git a/headers/meta.hpp/meta_value.hpp b/headers/meta.hpp/meta_value.hpp index 12737f2..e88a78c 100644 --- a/headers/meta.hpp/meta_value.hpp +++ b/headers/meta.hpp/meta_value.hpp @@ -53,33 +53,36 @@ namespace meta_hpp value& operator=(value&&) = default; value& operator=(const value&) = default; - template < typename T - , typename U = std::decay_t - , typename = std::enable_if_t> > + template < typename T, typename Tp = std::decay_t + , typename = std::enable_if_t> > value(T&& val) : raw_{std::forward(val)} - , fid_{get_family_id()} - , traits_{value_detail::get_traits()} {} + , fid_{get_family_id()} + , traits_{value_detail::get_traits()} {} - template < typename T - , typename U = std::decay_t - , typename = std::enable_if_t> > + template < typename T, typename Tp = std::decay_t + , typename = std::enable_if_t> > value& operator=(T&& val) { value{std::forward(val)}.swap(*this); return *this; } - template < typename T, typename... Args > + template < typename T, typename Tp = std::decay_t, typename... Args > explicit value(std::in_place_type_t, Args&&... args) - : raw_{std::in_place_type, std::forward(args)...} - , fid_{get_family_id()} - , traits_{value_detail::get_traits()} {} + : raw_{std::in_place_type, std::forward(args)...} + , fid_{get_family_id()} + , traits_{value_detail::get_traits()} {} - template < typename T, typename U, typename... Args > - explicit value(std::in_place_type_t, std::initializer_list ilist, Args&&... args) - : raw_{std::in_place_type, ilist, std::forward(args)...} - , fid_{get_family_id()} - , traits_{value_detail::get_traits()} {} + template < typename T, typename Tp = std::decay_t, typename I, typename... Args > + explicit value(std::in_place_type_t, std::initializer_list ilist, Args&&... args) + : raw_{std::in_place_type, ilist, std::forward(args)...} + , fid_{get_family_id()} + , traits_{value_detail::get_traits()} {} + + template < typename T > + bool has_type() const noexcept { + return fid_ == get_family_id(); + } template < typename T > T cast() && { @@ -129,12 +132,11 @@ namespace meta_hpp swap(traits_, other.traits_); } - template < typename T - , typename U = std::decay_t - , typename = std::enable_if_t> > + template < typename T, typename Tp = std::decay_t + , typename = std::enable_if_t> > bool equals(T&& other) const { - return fid() == get_family_id() - && std::equal_to<>{}(*try_cast(), std::forward(other)); + return fid_ == get_family_id() + && std::equal_to<>{}(*try_cast(), std::forward(other)); } bool equals(const value& other) const { @@ -146,7 +148,7 @@ namespace meta_hpp unsigned to_uint() const { return cast(); } float to_float() const { return cast(); } double to_double() const { return cast(); } - std::string to_string() const { return cast(); } + const std::string& to_string() const { return cast(); } std::int8_t to_int8() const { return cast(); } std::int16_t to_int16() const { return cast(); } @@ -162,26 +164,26 @@ namespace meta_hpp std::size_t to_size_t() const { return cast(); } std::uintptr_t to_uintptr_t() const { return cast(); } public: - bool is_bool() const noexcept { return !!try_cast(); } - bool is_int() const noexcept { return !!try_cast(); } - bool is_uint() const noexcept { return !!try_cast(); } - bool is_float() const noexcept { return !!try_cast(); } - bool is_double() const noexcept { return !!try_cast(); } - bool is_string() const noexcept { return !!try_cast(); } + bool is_bool() const noexcept { return has_type(); } + bool is_int() const noexcept { return has_type(); } + bool is_uint() const noexcept { return has_type(); } + bool is_float() const noexcept { return has_type(); } + bool is_double() const noexcept { return has_type(); } + bool is_string() const noexcept { return has_type(); } - bool is_int8() const noexcept { return !!try_cast(); } - bool is_int16() const noexcept { return !!try_cast(); } - bool is_int32() const noexcept { return !!try_cast(); } - bool is_int64() const noexcept { return !!try_cast(); } - bool is_ptrdiff_t() const noexcept { return !!try_cast(); } - bool is_intptr_t() const noexcept { return !!try_cast(); } + bool is_int8() const noexcept { return has_type(); } + bool is_int16() const noexcept { return has_type(); } + bool is_int32() const noexcept { return has_type(); } + bool is_int64() const noexcept { return has_type(); } + bool is_ptrdiff_t() const noexcept { return has_type(); } + bool is_intptr_t() const noexcept { return has_type(); } - bool is_uint8() const noexcept { return !!try_cast(); } - bool is_uint16() const noexcept { return !!try_cast(); } - bool is_uint32() const noexcept { return !!try_cast(); } - bool is_uint64() const noexcept { return !!try_cast(); } - bool is_size_t() const noexcept { return !!try_cast(); } - bool is_uintptr_t() const noexcept { return !!try_cast(); } + bool is_uint8() const noexcept { return has_type(); } + bool is_uint16() const noexcept { return has_type(); } + bool is_uint32() const noexcept { return has_type(); } + bool is_uint64() const noexcept { return has_type(); } + bool is_size_t() const noexcept { return has_type(); } + bool is_uintptr_t() const noexcept { return has_type(); } private: std::any raw_; family_id fid_; @@ -213,7 +215,7 @@ namespace meta_hpp::value_detail if constexpr ( std::is_invocable_v, T, T> ) { return std::equal_to<>{}(*l.try_cast(), *r.try_cast()); } else { - return std::addressof(l) == std::addressof(r); + return value_cdata(l) == value_cdata(r); } } } diff --git a/headers/meta.hpp/meta_variable_info.hpp b/headers/meta.hpp/meta_variable_info.hpp index 01f25f6..a338e78 100644 --- a/headers/meta.hpp/meta_variable_info.hpp +++ b/headers/meta.hpp/meta_variable_info.hpp @@ -96,11 +96,25 @@ namespace meta_hpp return getter_(); } + template < typename R, typename Rp = std::decay_t > + Rp get_r() const { + return get().template cast(); + } + template < typename Value > void set(Value&& value) const { return setter_(std::forward(value)); } + value operator()() const { + return get(); + } + + template < typename Value > + void operator()(Value&& value) const { + return set(std::forward(value)); + } + template < typename F > void each_data(F&& f) const { for ( auto&& id_info : datas_ ) { diff --git a/untests/meta_ctor_tests.cpp b/untests/meta_ctor_tests.cpp new file mode 100644 index 0000000..d284373 --- /dev/null +++ b/untests/meta_ctor_tests.cpp @@ -0,0 +1,138 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include +#include + +#include "doctest/doctest.hpp" + +namespace +{ + class clazz { + public: + int v1{1}; + int v2{2}; + + clazz() = default; + clazz(int v): v1{v}, v2{v} {} + clazz(int v1, int v2): v1{v1}, v2{v2} {} + }; +} + +TEST_CASE("meta/ctor") { + namespace meta = meta_hpp; + + const meta::ctor_info ctor0 = meta::ctor_<>().make_info(); + const meta::ctor_info ctor1 = meta::ctor_().make_info(); + const meta::ctor_info ctor2 = meta::ctor_().make_info(); + + SUBCASE("arity") { + CHECK(ctor0.arity() == 0u); + CHECK(ctor1.arity() == 1u); + CHECK(ctor2.arity() == 2u); + } + + SUBCASE("return_type") { + CHECK(ctor0.return_type() == meta::get_family_id()); + CHECK(ctor1.return_type() == meta::get_family_id()); + CHECK(ctor2.return_type() == meta::get_family_id()); + } + + SUBCASE("argument_types") { + CHECK_FALSE(ctor0.argument_type(0u)); + + CHECK(ctor1.argument_type(0u) == meta::get_family_id()); + CHECK_FALSE(ctor1.argument_type(1u)); + + CHECK(ctor2.argument_type(0u) == meta::get_family_id()); + CHECK(ctor2.argument_type(1u) == meta::get_family_id()); + CHECK_FALSE(ctor2.argument_type(2u)); + } + + SUBCASE("invoke0") { + CHECK(ctor0().cast().v1 == 1); + CHECK(ctor0().cast().v2 == 2); + CHECK_THROWS_AS(ctor0(1), std::logic_error); + + CHECK(ctor0.invoke().cast().v1 == 1); + CHECK(ctor0.invoke().cast().v2 == 2); + CHECK_THROWS_AS(ctor0.invoke(1), std::logic_error); + + CHECK(ctor0.invoke_r().v1 == 1); + CHECK(ctor0.invoke_r().v2 == 2); + CHECK_THROWS_AS(ctor0.invoke_r(1), std::logic_error); + } + + SUBCASE("invoke1") { + CHECK(ctor1(42).cast().v1 == 42); + CHECK(ctor1(42).cast().v2 == 42); + CHECK_THROWS_AS(ctor1(), std::logic_error); + CHECK_THROWS_AS(ctor1(1,1), std::logic_error); + + CHECK(ctor1.invoke(42).cast().v1 == 42); + CHECK(ctor1.invoke(42).cast().v2 == 42); + CHECK_THROWS_AS(ctor1.invoke(), std::logic_error); + CHECK_THROWS_AS(ctor1.invoke(1,1), std::logic_error); + + CHECK(ctor1.invoke_r(42).v1 == 42); + CHECK(ctor1.invoke_r(42).v2 == 42); + CHECK_THROWS_AS(ctor1.invoke_r(), std::logic_error); + CHECK_THROWS_AS(ctor1.invoke_r(1,1), std::logic_error); + } + + SUBCASE("invoke2") { + CHECK(ctor2(21,42).cast().v1 == 21); + CHECK(ctor2(21,42).cast().v2 == 42); + CHECK_THROWS_AS(ctor2(), std::logic_error); + CHECK_THROWS_AS(ctor2(1), std::logic_error); + CHECK_THROWS_AS(ctor2(1,1,1), std::logic_error); + + CHECK(ctor2.invoke(21,42).cast().v1 == 21); + CHECK(ctor2.invoke(21,42).cast().v2 == 42); + CHECK_THROWS_AS(ctor2.invoke(), std::logic_error); + CHECK_THROWS_AS(ctor2.invoke(1), std::logic_error); + CHECK_THROWS_AS(ctor2.invoke(1,1,1), std::logic_error); + + CHECK(ctor2.invoke_r(21,42).v1 == 21); + CHECK(ctor2.invoke_r(21,42).v2 == 42); + CHECK_THROWS_AS(ctor2.invoke_r(), std::logic_error); + CHECK_THROWS_AS(ctor2.invoke_r(1), std::logic_error); + CHECK_THROWS_AS(ctor2.invoke_r(1,1,1), std::logic_error); + } + + SUBCASE("is_invocable") { + CHECK(ctor0.is_invocable<>()); + CHECK_FALSE(ctor0.is_invocable()); + + CHECK(ctor1.is_invocable()); + CHECK_FALSE(ctor1.is_invocable()); + CHECK_FALSE(ctor1.is_invocable<>()); + CHECK_FALSE(ctor1.is_invocable()); + + CHECK(ctor2.is_invocable()); + CHECK_FALSE(ctor2.is_invocable()); + CHECK_FALSE(ctor2.is_invocable<>()); + CHECK_FALSE(ctor2.is_invocable()); + } +} + +TEST_CASE("meta/ctor/class") { + namespace meta = meta_hpp; + + const meta::class_info clazz_info = meta::class_("clazz")( + meta::ctor_<>(), + meta::ctor_(), + meta::ctor_() + ).make_info(); + + CHECK(clazz_info.get_ctor<>()); + CHECK(clazz_info.get_ctor()); + CHECK(clazz_info.get_ctor()); + + CHECK_FALSE(clazz_info.get_ctor()); + CHECK_FALSE(clazz_info.get_ctor()); + CHECK_FALSE(clazz_info.get_ctor()); +} diff --git a/untests/meta_field_tests.cpp b/untests/meta_field_tests.cpp index 759276a..b27afdc 100644 --- a/untests/meta_field_tests.cpp +++ b/untests/meta_field_tests.cpp @@ -37,14 +37,24 @@ TEST_CASE("meta/field") { clazz instance; CHECK(instance.field == 1); + CHECK(field_info.get_r(instance) == 1); + CHECK(field_info(instance).cast() == 1); CHECK(field_info.get(instance).cast() == 1); + CHECK(field_info.get_r(std::as_const(instance)) == 1); + CHECK(field_info(std::as_const(instance)).cast() == 1); CHECK(field_info.get(std::as_const(instance)).cast() == 1); + CHECK_NOTHROW(field_info(instance, 3)); CHECK_NOTHROW(field_info.set(instance, 3)); + CHECK_THROWS_AS(field_info(instance, 4.f), std::logic_error); CHECK_THROWS_AS(field_info.set(instance, 4.f), std::logic_error); CHECK(instance.field == 3); + CHECK(field_info.get_r(instance) == 3); + CHECK(field_info(instance).cast() == 3); CHECK(field_info.get(instance).cast() == 3); + CHECK(field_info.get_r(std::as_const(instance)) == 3); + CHECK(field_info(std::as_const(instance)).cast() == 3); CHECK(field_info.get(std::as_const(instance)).cast() == 3); } @@ -52,13 +62,22 @@ TEST_CASE("meta/field") { clazz instance; CHECK(instance.cfield == 2); + CHECK(cfield_info.get_r(instance) == 2); + CHECK(cfield_info(instance).cast() == 2); CHECK(cfield_info.get(instance).cast() == 2); + CHECK(cfield_info.get_r(std::as_const(instance)) == 2); + CHECK(cfield_info(std::as_const(instance)).cast() == 2); CHECK(cfield_info.get(std::as_const(instance)).cast() == 2); + CHECK_THROWS_AS(cfield_info(instance, 4), std::logic_error); CHECK_THROWS_AS(cfield_info.set(instance, 4), std::logic_error); CHECK(instance.cfield == 2); + CHECK(cfield_info.get_r(instance) == 2); + CHECK(cfield_info(instance).cast() == 2); CHECK(cfield_info.get(instance).cast() == 2); + CHECK(cfield_info.get_r(std::as_const(instance)) == 2); + CHECK(cfield_info(std::as_const(instance)).cast() == 2); CHECK(cfield_info.get(std::as_const(instance)).cast() == 2); } @@ -66,7 +85,11 @@ TEST_CASE("meta/field") { clazz instance; instance.field = 5; + CHECK(field_info.get_r(instance) == 5); + CHECK(field_info(instance).cast() == 5); CHECK(field_info.get(instance).cast() == 5); + CHECK(field_info.get_r(std::as_const(instance)) == 5); + CHECK(field_info(std::as_const(instance)).cast() == 5); CHECK(field_info.get(std::as_const(instance)).cast() == 5); } } diff --git a/untests/meta_function_tests.cpp b/untests/meta_function_tests.cpp index f5c508a..93cbc2c 100644 --- a/untests/meta_function_tests.cpp +++ b/untests/meta_function_tests.cpp @@ -64,33 +64,52 @@ TEST_CASE("meta/function") { } SUBCASE("void_return") { - CHECK_NOTHROW(void_f_void_info.invoke()); + CHECK_FALSE(void_f_void_info()); + CHECK_FALSE(void_f_void_info.invoke()); + CHECK_FALSE(void_f_void_info.invoke_r()); + CHECK_THROWS_AS(void_f_void_info(1), std::logic_error); CHECK_THROWS_AS(void_f_void_info.invoke(1), std::logic_error); + CHECK_THROWS_AS(void_f_int_info(), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(), std::logic_error); - CHECK_NOTHROW(void_f_int_info.invoke(1)); + CHECK_FALSE(void_f_int_info(1)); + CHECK_FALSE(void_f_int_info.invoke(1)); + CHECK_FALSE(void_f_int_info.invoke_r(1)); + CHECK_THROWS_AS(void_f_int_info(1.f), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(1.f), std::logic_error); + CHECK_THROWS_AS(void_f_int_info(1, 2), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(1, 2), std::logic_error); + CHECK_THROWS_AS(void_f_int2_info(), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(), std::logic_error); + CHECK_THROWS_AS(void_f_int2_info(1), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(1), std::logic_error); - CHECK_NOTHROW(void_f_int2_info.invoke(1, 2)); + CHECK_FALSE(void_f_int2_info(1, 2)); + CHECK_FALSE(void_f_int2_info.invoke(1, 2)); + CHECK_FALSE(void_f_int2_info.invoke_r(1, 2)); + CHECK_THROWS_AS(void_f_int2_info(1.f, 2), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(1.f, 2), std::logic_error); + CHECK_THROWS_AS(void_f_int2_info(1, 2.f), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(1, 2.f), std::logic_error); + CHECK_THROWS_AS(void_f_int2_info(1, 2, 3), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(1, 2, 3), std::logic_error); } SUBCASE("int_return") { + CHECK(int_f_void_info.invoke_r() == 1); CHECK(int_f_void_info.invoke()->cast() == 1); CHECK_THROWS_AS(int_f_void_info.invoke(1), std::logic_error); + CHECK_THROWS_AS(int_f_void_info.invoke_r(1), std::logic_error); CHECK_THROWS_AS(int_f_int_info.invoke(), std::logic_error); + CHECK(int_f_int_info.invoke_r(1) == 1); CHECK(int_f_int_info.invoke(1)->cast() == 1); CHECK_THROWS_AS(int_f_int_info.invoke(1.f), std::logic_error); CHECK_THROWS_AS(int_f_int_info.invoke(1, 2), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(1), std::logic_error); + CHECK(int_f_int2_info.invoke_r(1, 2) == 3); CHECK(int_f_int2_info.invoke(1, 2)->cast() == 3); CHECK_THROWS_AS(int_f_int2_info.invoke(1.f, 2), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(1, 2.f), std::logic_error); diff --git a/untests/meta_method_tests.cpp b/untests/meta_method_tests.cpp index dcd0881..c277ae6 100644 --- a/untests/meta_method_tests.cpp +++ b/untests/meta_method_tests.cpp @@ -83,64 +83,106 @@ TEST_CASE("meta/non_const_method") { SUBCASE("another_instance") { clazz2 instance; + CHECK_THROWS_AS(void_f_void_info(instance), std::logic_error); CHECK_THROWS_AS(void_f_void_info.invoke(instance), std::logic_error); + CHECK_THROWS_AS(void_f_void_info.invoke_r(instance), std::logic_error); + + CHECK_THROWS_AS(void_f_int_info(instance, 1), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1), std::logic_error); + CHECK_THROWS_AS(void_f_int_info.invoke_r(instance, 1), std::logic_error); + + CHECK_THROWS_AS(void_f_int2_info(instance, 1, 2), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2), std::logic_error); + CHECK_THROWS_AS(void_f_int2_info.invoke_r(instance, 1, 2), std::logic_error); } SUBCASE("void_return") { clazz instance; - CHECK_NOTHROW(void_f_void_info.invoke(instance)); + CHECK_FALSE(void_f_void_info(instance)); + CHECK_FALSE(void_f_void_info.invoke(instance)); + CHECK_FALSE(void_f_void_info.invoke_r(instance)); + CHECK_THROWS_AS(void_f_void_info(instance, 1), std::logic_error); CHECK_THROWS_AS(void_f_void_info.invoke(instance, 1), std::logic_error); + CHECK_THROWS_AS(void_f_void_info.invoke_r(instance, 1), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(instance), std::logic_error); - CHECK_NOTHROW(void_f_int_info.invoke(instance, 1)); + CHECK_FALSE(void_f_int_info(instance, 1)); + CHECK_FALSE(void_f_int_info.invoke(instance, 1)); + CHECK_FALSE(void_f_int_info.invoke_r(instance, 1)); CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1.f), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1, 2), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1), std::logic_error); - CHECK_NOTHROW(void_f_int2_info.invoke(instance, 1, 2)); + CHECK_FALSE(void_f_int2_info(instance, 1, 2)); + CHECK_FALSE(void_f_int2_info.invoke(instance, 1, 2)); + CHECK_FALSE(void_f_int2_info.invoke_r(instance, 1, 2)); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1.f, 2), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2.f), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2, 3), std::logic_error); const clazz& cinstance = instance; + CHECK_THROWS_AS(void_f_void_info(cinstance), std::logic_error); CHECK_THROWS_AS(void_f_void_info.invoke(cinstance), std::logic_error); + CHECK_THROWS_AS(void_f_void_info.invoke_r(cinstance), std::logic_error); + CHECK_THROWS_AS(void_f_int_info(cinstance, 1), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(cinstance, 1), std::logic_error); + CHECK_THROWS_AS(void_f_int_info.invoke_r(cinstance, 1), std::logic_error); + CHECK_THROWS_AS(void_f_int2_info(cinstance, 1, 2), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(cinstance, 1, 2), std::logic_error); + CHECK_THROWS_AS(void_f_int2_info.invoke_r(cinstance, 1, 2), std::logic_error); } SUBCASE("int_return") { clazz instance; + CHECK(int_f_void_info(instance)->cast() == 1); CHECK(int_f_void_info.invoke(instance)->cast() == 1); + CHECK(int_f_void_info.invoke_r(instance) == 1); + CHECK_THROWS_AS(int_f_void_info(instance, 1), std::logic_error); CHECK_THROWS_AS(int_f_void_info.invoke(instance, 1), std::logic_error); + CHECK_THROWS_AS(int_f_void_info.invoke_r(instance, 1), std::logic_error); CHECK_THROWS_AS(int_f_int_info.invoke(instance), std::logic_error); + CHECK(int_f_int_info(instance, 1)->cast() == 1); CHECK(int_f_int_info.invoke(instance, 1)->cast() == 1); + CHECK(int_f_int_info.invoke_r(instance, 1) == 1); CHECK_THROWS_AS(int_f_int_info.invoke(instance, 1.f), std::logic_error); CHECK_THROWS_AS(int_f_int_info.invoke(instance, 1, 2), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(instance), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1), std::logic_error); + CHECK(int_f_int2_info(instance, 1, 2)->cast() == 3); CHECK(int_f_int2_info.invoke(instance, 1, 2)->cast() == 3); + CHECK(int_f_int2_info.invoke_r(instance, 1, 2) == 3); CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1.f, 2), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1, 2.f), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1, 2, 3), std::logic_error); const clazz& cinstance = instance; + CHECK_THROWS_AS(int_f_void_info(cinstance), std::logic_error); CHECK_THROWS_AS(int_f_void_info.invoke(cinstance), std::logic_error); + CHECK_THROWS_AS(int_f_void_info.invoke_r(cinstance), std::logic_error); + CHECK_THROWS_AS(int_f_int_info(cinstance, 1), std::logic_error); CHECK_THROWS_AS(int_f_int_info.invoke(cinstance, 1), std::logic_error); + CHECK_THROWS_AS(int_f_int_info.invoke_r(cinstance, 1), std::logic_error); + CHECK_THROWS_AS(int_f_int2_info(cinstance, 1, 2), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(cinstance, 1, 2), std::logic_error); + CHECK_THROWS_AS(int_f_int2_info.invoke_r(cinstance, 1, 2), std::logic_error); } SUBCASE("int_return_by_value") { meta::value instance{clazz{}}; + CHECK(int_f_void_info(instance)->cast() == 1); CHECK(int_f_void_info.invoke(instance)->cast() == 1); + CHECK(int_f_void_info.invoke_r(instance) == 1); + CHECK(int_f_int_info(instance, 1)->cast() == 1); CHECK(int_f_int_info.invoke(instance, 1)->cast() == 1); + CHECK(int_f_int_info.invoke_r(instance, 1) == 1); + CHECK(int_f_int2_info(instance, 1, 2)->cast() == 3); CHECK(int_f_int2_info.invoke(instance, 1, 2)->cast() == 3); + CHECK(int_f_int2_info.invoke_r(instance, 1, 2) == 3); } } @@ -186,63 +228,90 @@ TEST_CASE("meta/const_method") { SUBCASE("another_instance") { const clazz2 instance; + CHECK_THROWS_AS(void_f_void_info(instance), std::logic_error); CHECK_THROWS_AS(void_f_void_info.invoke(instance), std::logic_error); + CHECK_THROWS_AS(void_f_int_info(instance, 1), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1), std::logic_error); + CHECK_THROWS_AS(void_f_int2_info(instance, 1, 2), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2), std::logic_error); } SUBCASE("void_return") { clazz instance; - CHECK_NOTHROW(void_f_void_info.invoke(instance)); + CHECK_FALSE(void_f_void_info(instance)); + CHECK_FALSE(void_f_void_info.invoke(instance)); CHECK_THROWS_AS(void_f_void_info.invoke(instance, 1), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(instance), std::logic_error); - CHECK_NOTHROW(void_f_int_info.invoke(instance, 1)); + CHECK_FALSE(void_f_int_info(instance, 1)); + CHECK_FALSE(void_f_int_info.invoke(instance, 1)); CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1.f), std::logic_error); CHECK_THROWS_AS(void_f_int_info.invoke(instance, 1, 2), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1), std::logic_error); - CHECK_NOTHROW(void_f_int2_info.invoke(instance, 1, 2)); + CHECK_FALSE(void_f_int2_info(instance, 1, 2)); + CHECK_FALSE(void_f_int2_info.invoke(instance, 1, 2)); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1.f, 2), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2.f), std::logic_error); CHECK_THROWS_AS(void_f_int2_info.invoke(instance, 1, 2, 3), std::logic_error); const clazz& cinstance = instance; - CHECK_NOTHROW(void_f_void_info.invoke(cinstance)); - CHECK_NOTHROW(void_f_int_info.invoke(cinstance, 1)); - CHECK_NOTHROW(void_f_int2_info.invoke(cinstance, 1, 2)); + CHECK_FALSE(void_f_void_info(cinstance)); + CHECK_FALSE(void_f_void_info.invoke(cinstance)); + CHECK_FALSE(void_f_int_info(cinstance, 1)); + CHECK_FALSE(void_f_int_info.invoke(cinstance, 1)); + CHECK_FALSE(void_f_int2_info(cinstance, 1, 2)); + CHECK_FALSE(void_f_int2_info.invoke(cinstance, 1, 2)); } SUBCASE("int_return") { clazz instance; + CHECK(int_f_void_info(instance)->cast() == 1); CHECK(int_f_void_info.invoke(instance)->cast() == 1); + CHECK(int_f_void_info.invoke_r(instance) == 1); CHECK_THROWS_AS(int_f_void_info.invoke(instance, 1), std::logic_error); CHECK_THROWS_AS(int_f_int_info.invoke(instance), std::logic_error); + CHECK(int_f_int_info(instance, 1)->cast() == 1); CHECK(int_f_int_info.invoke(instance, 1)->cast() == 1); + CHECK(int_f_int_info.invoke_r(instance, 1) == 1); CHECK_THROWS_AS(int_f_int_info.invoke(instance, 1.f), std::logic_error); CHECK_THROWS_AS(int_f_int_info.invoke(instance, 1, 2), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(instance), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1), std::logic_error); + CHECK(int_f_int2_info(instance, 1, 2)->cast() == 3); CHECK(int_f_int2_info.invoke(instance, 1, 2)->cast() == 3); + CHECK(int_f_int2_info.invoke_r(instance, 1, 2) == 3); CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1.f, 2), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1, 2.f), std::logic_error); CHECK_THROWS_AS(int_f_int2_info.invoke(instance, 1, 2, 3), std::logic_error); const clazz& cinstance = instance; + CHECK(int_f_void_info(cinstance)->cast() == 1); CHECK(int_f_void_info.invoke(cinstance)->cast() == 1); + CHECK(int_f_void_info.invoke_r(cinstance) == 1); + CHECK(int_f_int_info(cinstance, 1)->cast() == 1); CHECK(int_f_int_info.invoke(cinstance, 1)->cast() == 1); + CHECK(int_f_int_info.invoke_r(cinstance, 1) == 1); + CHECK(int_f_int2_info(cinstance, 1, 2)->cast() == 3); CHECK(int_f_int2_info.invoke(cinstance, 1, 2)->cast() == 3); + CHECK(int_f_int2_info.invoke_r(cinstance, 1, 2) == 3); } SUBCASE("int_return_by_value") { meta::value instance{clazz{}}; + CHECK(int_f_void_info(instance)->cast() == 1); CHECK(int_f_void_info.invoke(instance)->cast() == 1); + CHECK(int_f_void_info.invoke_r(instance) == 1); + CHECK(int_f_int_info(instance, 1)->cast() == 1); CHECK(int_f_int_info.invoke(instance, 1)->cast() == 1); + CHECK(int_f_int_info.invoke_r(instance, 1) == 1); + CHECK(int_f_int2_info(instance, 1, 2)->cast() == 3); CHECK(int_f_int2_info.invoke(instance, 1, 2)->cast() == 3); + CHECK(int_f_int2_info.invoke_r(instance, 1, 2) == 3); } } diff --git a/untests/meta_value_tests.cpp b/untests/meta_value_tests.cpp index 9231483..bb06099 100644 --- a/untests/meta_value_tests.cpp +++ b/untests/meta_value_tests.cpp @@ -69,14 +69,25 @@ TEST_CASE("meta/value") { CHECK(meta::value{std::in_place_type, std::uint64_t{1}}.is_uint64()); CHECK(meta::value{std::in_place_type, std::size_t{1}}.is_size_t()); CHECK(meta::value{std::in_place_type, std::uintptr_t{1}}.is_uintptr_t()); + + SUBCASE("in_place") { + CHECK(meta::value{std::in_place_type, std::uint8_t{1}}.is_uint8()); + CHECK(meta::value{std::in_place_type, std::uint8_t{1}}.is_uint8()); + CHECK(meta::value{std::in_place_type, std::uint8_t{1}}.is_uint8()); + CHECK(meta::value{std::in_place_type, std::uint8_t{1}}.is_uint8()); + } } TEST_CASE("meta/value/fid") { namespace meta = meta_hpp; using namespace std::string_literals; + CHECK(meta::value{clazz{}}.has_type()); CHECK(meta::value{clazz{}}.fid() == meta::get_family_id()); + + CHECK(meta::value{clazz2{}}.has_type()); CHECK(meta::value{clazz2{}}.fid() == meta::get_family_id()); + CHECK(meta::value{clazz{}}.fid() != meta::value{clazz2{}}.fid()); { diff --git a/untests/meta_variable_tests.cpp b/untests/meta_variable_tests.cpp index 69318bc..0acc5b8 100644 --- a/untests/meta_variable_tests.cpp +++ b/untests/meta_variable_tests.cpp @@ -39,28 +39,41 @@ TEST_CASE("meta/variable") { { CHECK(variable == 1); + CHECK(variable_info().cast() == 1); CHECK(variable_info.get().cast() == 1); + CHECK(variable_info.get_r() == 1); + CHECK_NOTHROW(variable_info(3)); CHECK_NOTHROW(variable_info.set(3)); + CHECK_THROWS_AS(variable_info(4.f), std::logic_error); CHECK_THROWS_AS(variable_info.set(4.f), std::logic_error); CHECK(variable == 3); + CHECK(variable_info().cast() == 3); CHECK(variable_info.get().cast() == 3); + CHECK(variable_info.get_r() == 3); } { CHECK(cvariable == 2); + CHECK(cvariable_info().cast() == 2); CHECK(cvariable_info.get().cast() == 2); + CHECK(cvariable_info.get_r() == 2); + CHECK_THROWS_AS(cvariable_info(4), std::logic_error); CHECK_THROWS_AS(cvariable_info.set(4), std::logic_error); CHECK(cvariable == 2); + CHECK(cvariable_info().cast() == 2); CHECK(cvariable_info.get().cast() == 2); + CHECK(cvariable_info.get_r() == 2); } { variable = 5; + CHECK(variable_info().cast() == 5); CHECK(variable_info.get().cast() == 5); + CHECK(variable_info.get_r() == 5); } } @@ -78,27 +91,39 @@ TEST_CASE("meta/variable") { { CHECK(clazz::variable == 1); + CHECK(variable_info().cast() == 1); CHECK(variable_info.get().cast() == 1); + CHECK(variable_info.get_r() == 1); + CHECK_NOTHROW(variable_info(3)); CHECK_NOTHROW(variable_info.set(3)); CHECK(clazz::variable == 3); + CHECK(variable_info().cast() == 3); CHECK(variable_info.get().cast() == 3); + CHECK(variable_info.get_r() == 3); } { CHECK(clazz::cvariable == 2); + CHECK(cvariable_info().cast() == 2); CHECK(cvariable_info.get().cast() == 2); + CHECK(cvariable_info.get_r() == 2); + CHECK_THROWS_AS(cvariable_info(4), std::logic_error); CHECK_THROWS_AS(cvariable_info.set(4), std::logic_error); CHECK(clazz::cvariable == 2); + CHECK(cvariable_info().cast() == 2); CHECK(cvariable_info.get().cast() == 2); + CHECK(cvariable_info.get_r() == 2); } { clazz::variable = 5; + CHECK(variable_info().cast() == 5); CHECK(variable_info.get().cast() == 5); + CHECK(variable_info.get_r() == 5); } } }