empty value instead std::optional

This commit is contained in:
BlackMATov
2022-01-24 04:20:27 +07:00
parent fc69b71779
commit 193e8eddd1
12 changed files with 75 additions and 94 deletions

View File

@@ -19,7 +19,6 @@
#include <iosfwd>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <span>
#include <stdexcept>

View File

@@ -211,10 +211,10 @@ namespace meta_hpp
[[nodiscard]] const std::string& get_name() const noexcept;
template < typename... Args >
std::optional<value> invoke(Args&&... args) const;
value invoke(Args&&... args) const;
template < typename... Args >
std::optional<value> operator()(Args&&... args) const;
value operator()(Args&&... args) const;
template < typename... Args >
[[nodiscard]] bool is_invocable_with() const noexcept;
@@ -277,10 +277,10 @@ namespace meta_hpp
[[nodiscard]] const std::string& get_name() const noexcept;
template < typename Instance, typename... Args >
std::optional<value> invoke(Instance&& instance, Args&&... args) const;
value invoke(Instance&& instance, Args&&... args) const;
template < typename Instance, typename... Args >
std::optional<value> operator()(Instance&& instance, Args&&... args) const;
value operator()(Instance&& instance, Args&&... args) const;
template < typename Instance, typename... Args >
[[nodiscard]] bool is_invocable_with() const noexcept;
@@ -388,7 +388,7 @@ namespace meta_hpp::detail
};
struct function_state final {
using invoke_impl = std::function<std::optional<value>(std::span<const arg>)>;
using invoke_impl = std::function<value(std::span<const arg>)>;
using is_invocable_with_impl = std::function<bool(std::span<const arg_base>)>;
const function_index index;
@@ -417,7 +417,7 @@ namespace meta_hpp::detail
};
struct method_state final {
using invoke_impl = std::function<std::optional<value>(const inst&, std::span<const arg>)>;
using invoke_impl = std::function<value(const inst&, std::span<const arg>)>;
using is_invocable_with_impl = std::function<bool(const inst_base&, std::span<const arg_base>)>;
const method_index index;

View File

@@ -14,7 +14,7 @@
namespace meta_hpp::detail
{
template < function_policy_kind Policy, function_kind Function >
std::optional<value> raw_function_invoke(Function function, std::span<const arg> args) {
value raw_function_invoke(Function function, std::span<const arg> args) {
using ft = function_traits<Function>;
using return_type = typename ft::return_type;
using argument_types = typename ft::argument_types;
@@ -40,7 +40,7 @@ namespace meta_hpp::detail
return std::invoke([
args, function = std::move(function)
// NOLINTNEXTLINE(readability-named-parameter)
]<std::size_t... Is>(std::index_sequence<Is...>) -> std::optional<value> {
]<std::size_t... Is>(std::index_sequence<Is...>) -> value {
if ( !(... && (args.data() + Is)->can_cast_to<type_list_at_t<Is, argument_types>>()) ) {
throw std::logic_error("an attempt to call a function with incorrect argument types");
}
@@ -49,7 +49,7 @@ namespace meta_hpp::detail
std::ignore = std::invoke(
std::move(function),
(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...);
return std::nullopt;
return {};
} else {
return_type&& return_value = std::invoke(
std::move(function),
@@ -134,7 +134,7 @@ namespace meta_hpp
}
template < typename... Args >
std::optional<value> function::invoke(Args&&... args) const {
value function::invoke(Args&&... args) const {
if constexpr ( sizeof...(Args) > 0 ) {
using namespace detail;
const std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
@@ -145,7 +145,7 @@ namespace meta_hpp
}
template < typename... Args >
std::optional<value> function::operator()(Args&&... args) const {
value function::operator()(Args&&... args) const {
return invoke(std::forward<Args>(args)...);
}

View File

@@ -14,7 +14,7 @@
namespace meta_hpp::detail
{
template < method_policy_kind Policy, method_kind Method >
std::optional<value> raw_method_invoke(Method method, const inst& inst, std::span<const arg> args) {
value raw_method_invoke(Method method, const inst& inst, std::span<const arg> args) {
using mt = method_traits<Method>;
using return_type = typename mt::return_type;
using qualified_type = typename mt::qualified_type;
@@ -46,7 +46,7 @@ namespace meta_hpp::detail
&inst, &args,
method = std::move(method)
// NOLINTNEXTLINE(readability-named-parameter)
]<std::size_t... Is>(std::index_sequence<Is...>) -> std::optional<value> {
]<std::size_t... Is>(std::index_sequence<Is...>) -> value {
if ( !(... && (args.data() + Is)->can_cast_to<type_list_at_t<Is, argument_types>>()) ) {
throw std::logic_error("an attempt to call a method with incorrect argument types");
}
@@ -56,7 +56,7 @@ namespace meta_hpp::detail
std::move(method),
inst.cast<qualified_type>(),
(args.data() + Is)->cast<type_list_at_t<Is, argument_types>>()...);
return std::nullopt;
return {};
} else {
return_type&& return_value = std::invoke(
std::move(method),
@@ -147,7 +147,7 @@ namespace meta_hpp
}
template < typename Instance, typename... Args >
std::optional<value> method::invoke(Instance&& instance, Args&&... args) const {
value method::invoke(Instance&& instance, Args&&... args) const {
using namespace detail;
const inst vinst{std::forward<Instance>(instance)};
if constexpr ( sizeof...(Args) > 0 ) {
@@ -159,7 +159,7 @@ namespace meta_hpp
}
template < typename Instance, typename... Args >
std::optional<value> method::operator()(Instance&& instance, Args&&... args) const {
value method::operator()(Instance&& instance, Args&&... args) const {
return invoke(std::forward<Instance>(instance), std::forward<Args>(args)...);
}

View File

@@ -220,10 +220,10 @@ namespace meta_hpp
[[nodiscard]] const variable_map& get_variables() const noexcept;
template < typename... Args >
[[nodiscard]] std::optional<value> create(Args&&... args) const;
[[nodiscard]] value create(Args&&... args) const;
template < typename... Args >
[[nodiscard]] std::optional<value> operator()(Args&&... args) const;
[[nodiscard]] value operator()(Args&&... args) const;
template < typename Arg >
bool destroy(Arg&& ptr) const;
@@ -315,8 +315,8 @@ namespace meta_hpp
[[nodiscard]] evalue get_evalue(std::string_view name) const noexcept;
template < typename Value >
[[nodiscard]] std::optional<std::string> value_to_name(Value&& value) const noexcept;
[[nodiscard]] std::optional<value> name_to_value(std::string_view name) const noexcept;
[[nodiscard]] std::string_view value_to_name(Value&& value) const noexcept;
[[nodiscard]] value name_to_value(std::string_view name) const noexcept;
private:
detail::enum_type_data_ptr data_;
friend auto detail::data_access<enum_type>(const enum_type&);

View File

@@ -103,17 +103,17 @@ namespace meta_hpp
}
template < typename... Args >
std::optional<value> class_type::create(Args&&... args) const {
value class_type::create(Args&&... args) const {
for ( auto&& ctor : data_->ctors ) {
if ( ctor.second.is_invocable_with(std::forward<Args>(args)...) ) {
return ctor.second.invoke(std::forward<Args>(args)...);
}
}
return std::nullopt;
return {};
}
template < typename... Args >
std::optional<value> class_type::operator()(Args&&... args) const {
value class_type::operator()(Args&&... args) const {
return create(std::forward<Args>(args)...);
}

View File

@@ -71,11 +71,11 @@ namespace meta_hpp
}
template < typename Value >
std::optional<std::string> enum_type::value_to_name(Value&& value) const noexcept {
std::string_view enum_type::value_to_name(Value&& value) const noexcept {
const detail::arg value_arg{std::forward<Value>(value)};
if ( value_arg.get_raw_type() != *this ) {
return std::nullopt;
return std::string_view{};
}
for ( auto&& evalue : data_->evalues ) {
@@ -84,13 +84,14 @@ namespace meta_hpp
}
}
return std::nullopt;
return std::string_view{};
}
inline std::optional<value> enum_type::name_to_value(std::string_view name) const noexcept {
inline value enum_type::name_to_value(std::string_view name) const noexcept {
if ( const evalue value = get_evalue(name); value ) {
return value.get_value();
}
return std::nullopt;
return value{};
}
}

View File

@@ -13,12 +13,12 @@
namespace meta_hpp
{
template < typename... Args >
std::optional<value> invoke(const function& function, Args&&... args) {
value invoke(const function& function, Args&&... args) {
return function.invoke(std::forward<Args>(args)...);
}
template < detail::function_kind Function, typename... Args >
std::optional<value> invoke(Function&& function, Args&&... args) {
value invoke(Function&& function, Args&&... args) {
using namespace detail;
if constexpr ( sizeof...(Args) > 0 ) {
const std::array<arg, sizeof...(Args)> vargs{arg{std::forward<Args>(args)}...};
@@ -32,12 +32,12 @@ namespace meta_hpp
namespace meta_hpp
{
template < typename Instance >
std::optional<value> invoke(const member& member, Instance&& instance) {
value invoke(const member& member, Instance&& instance) {
return member.get(std::forward<Instance>(instance));
}
template < detail::member_kind Member, typename Instance >
std::optional<value> invoke(Member&& member, Instance&& instance) {
value invoke(Member&& member, Instance&& instance) {
using namespace detail;
const inst vinst{std::forward<Instance>(instance)};
return raw_member_getter<member_policy::as_copy>(std::forward<Member>(member), vinst);
@@ -47,12 +47,12 @@ namespace meta_hpp
namespace meta_hpp
{
template < typename Instance, typename... Args >
std::optional<value> invoke(const method& method, Instance&& instance, Args&&... args) {
value invoke(const method& method, Instance&& instance, Args&&... args) {
return method.invoke(std::forward<Instance>(instance), std::forward<Args>(args)...);
}
template < detail::method_kind Method, typename Instance, typename... Args >
std::optional<value> invoke(Method&& method, Instance&& instance, Args&&... args) {
value invoke(Method&& method, Instance&& instance, Args&&... args) {
using namespace detail;
const inst vinst{std::forward<Instance>(instance)};
if constexpr ( sizeof...(Args) > 0 ) {

View File

@@ -89,7 +89,8 @@ TEST_CASE("meta/meta_states/ctor") {
REQUIRE(clazz_type);
{
const meta::value v = clazz_type.create(10).value();
CHECK_FALSE(clazz_type.create(10, 20));
const meta::value v = clazz_type.create(10);
CHECK(v.get_type() == meta::resolve_type<clazz<1>>());
CHECK(v.cast<clazz<1>>().i == 10);
@@ -108,7 +109,8 @@ TEST_CASE("meta/meta_states/ctor") {
REQUIRE(clazz_type);
{
const meta::value v = clazz_type.create(20).value();
CHECK_FALSE(clazz_type.create(10, 20));
const meta::value v = clazz_type.create(20);
CHECK(v.get_type() == meta::resolve_type<clazz<2>*>());
CHECK(v.cast<clazz<2>*>()->i == 20);
CHECK(clazz_type.destroy(v));
@@ -128,7 +130,8 @@ TEST_CASE("meta/meta_states/ctor") {
REQUIRE(clazz_type);
{
const meta::value v = clazz_type.create(30).value();
CHECK_FALSE(clazz_type.create(10, 20));
const meta::value v = clazz_type.create(30);
CHECK(v.get_type() == meta::resolve_type<std::shared_ptr<clazz<3>>>());
CHECK(v.cast<std::shared_ptr<clazz<3>>>()->i == 30);

View File

@@ -88,7 +88,7 @@ TEST_CASE("meta/meta_states/function") {
CHECK_THROWS(func.invoke(ivec2{}, ivec2{}, 42));
CHECK(func.invoke(ivec2{1,2}, ivec2{3,4}));
CHECK(func.invoke(ivec2{1,2}, ivec2{3,4}).value() == ivec2{4,6});
CHECK(func.invoke(ivec2{1,2}, ivec2{3,4}) == ivec2{4,6});
}
SUBCASE("ilength2") {
@@ -113,7 +113,7 @@ TEST_CASE("meta/meta_states/function") {
CHECK_THROWS(func.invoke(ivec2{}, 42));
CHECK(func.invoke(ivec2{2,3}));
CHECK(func.invoke(ivec2{2,3}).value() == 13);
CHECK(func.invoke(ivec2{2,3}) == 13);
}
SUBCASE("arg_null") {

View File

@@ -130,9 +130,9 @@ TEST_CASE("meta/meta_states/method") {
{
clazz cl;
CHECK(mi.invoke(cl).value() == 1);
CHECK(mi.invoke(cl) == 1);
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 1);
CHECK(mi.invoke(std::move(cl)) == 1);
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
}
@@ -175,9 +175,9 @@ TEST_CASE("meta/meta_states/method") {
{
clazz cl;
CHECK(mi.invoke(cl).value() == 2);
CHECK(mi.invoke(cl) == 2);
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 2);
CHECK(mi.invoke(std::move(cl)) == 2);
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
}
@@ -220,10 +220,10 @@ TEST_CASE("meta/meta_states/method") {
{
clazz cl;
CHECK(mi.invoke(cl).value() == 3);
CHECK(mi.invoke(std::as_const(cl)).value() == 3);
CHECK(mi.invoke(std::move(cl)).value() == 3);
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 3);
CHECK(mi.invoke(cl) == 3);
CHECK(mi.invoke(std::as_const(cl)) == 3);
CHECK(mi.invoke(std::move(cl)) == 3);
CHECK(mi.invoke(std::move(std::as_const(cl))) == 3);
}
static_assert(std::is_invocable_v<decltype(&clazz::const_method), clazz&>);
@@ -265,10 +265,10 @@ TEST_CASE("meta/meta_states/method") {
{
clazz cl;
CHECK(mi.invoke(cl).value() == 4);
CHECK(mi.invoke(std::as_const(cl)).value() == 4);
CHECK(mi.invoke(std::move(cl)).value() == 4);
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 4);
CHECK(mi.invoke(cl) == 4);
CHECK(mi.invoke(std::as_const(cl)) == 4);
CHECK(mi.invoke(std::move(cl)) == 4);
CHECK(mi.invoke(std::move(std::as_const(cl))) == 4);
}
static_assert(std::is_invocable_v<decltype(&clazz::const_method_noexcept), clazz&>);
@@ -310,7 +310,7 @@ TEST_CASE("meta/meta_states/method") {
{
clazz cl;
CHECK(mi.invoke(cl).value() == 5);
CHECK(mi.invoke(cl) == 5);
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK_THROWS(mi.invoke(std::move(cl)));
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
@@ -355,7 +355,7 @@ TEST_CASE("meta/meta_states/method") {
{
clazz cl;
CHECK(mi.invoke(cl).value() == 6);
CHECK(mi.invoke(cl) == 6);
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK_THROWS(mi.invoke(std::move(cl)));
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
@@ -400,8 +400,8 @@ TEST_CASE("meta/meta_states/method") {
{
clazz cl;
CHECK(mi.invoke(cl).value() == 7);
CHECK(mi.invoke(std::as_const(cl)).value() == 7);
CHECK(mi.invoke(cl) == 7);
CHECK(mi.invoke(std::as_const(cl)) == 7);
CHECK(mi.invoke(std::move(cl)) == 7);
CHECK(mi.invoke(std::move(std::as_const(cl))) == 7);
}
@@ -445,8 +445,8 @@ TEST_CASE("meta/meta_states/method") {
{
clazz cl;
CHECK(mi.invoke(cl).value() == 8);
CHECK(mi.invoke(std::as_const(cl)).value() == 8);
CHECK(mi.invoke(cl) == 8);
CHECK(mi.invoke(std::as_const(cl)) == 8);
CHECK(mi.invoke(std::move(cl)) == 8);
CHECK(mi.invoke(std::move(std::as_const(cl))) == 8);
}
@@ -492,7 +492,7 @@ TEST_CASE("meta/meta_states/method") {
CHECK_THROWS(mi.invoke(cl));
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 9);
CHECK(mi.invoke(std::move(cl)) == 9);
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
}
@@ -537,7 +537,7 @@ TEST_CASE("meta/meta_states/method") {
CHECK_THROWS(mi.invoke(cl));
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 10);
CHECK(mi.invoke(std::move(cl)) == 10);
CHECK_THROWS(mi.invoke(std::move(std::as_const(cl))));
}
@@ -582,8 +582,8 @@ TEST_CASE("meta/meta_states/method") {
CHECK_THROWS(mi.invoke(cl));
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 11);
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 11);
CHECK(mi.invoke(std::move(cl)) == 11);
CHECK(mi.invoke(std::move(std::as_const(cl))) == 11);
}
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_rref), clazz&>);
@@ -627,8 +627,8 @@ TEST_CASE("meta/meta_states/method") {
CHECK_THROWS(mi.invoke(cl));
CHECK_THROWS(mi.invoke(std::as_const(cl)));
CHECK(mi.invoke(std::move(cl)).value() == 12);
CHECK(mi.invoke(std::move(std::as_const(cl))).value() == 12);
CHECK(mi.invoke(std::move(cl)) == 12);
CHECK(mi.invoke(std::move(std::as_const(cl))) == 12);
}
static_assert(!std::is_invocable_v<decltype(&clazz::const_method_noexcept_rref), clazz&>);

View File

@@ -120,42 +120,20 @@ TEST_CASE("meta/meta_types/enum_type") {
const meta::enum_type color_type = meta::resolve_type<color>();
REQUIRE(color_type);
{
REQUIRE(color_type.value_to_name(color::red));
CHECK(color_type.value_to_name(color::red) == "red");
}
{
REQUIRE(color_type.value_to_name(meta::value{color::blue}));
CHECK(color_type.value_to_name(color::blue) == "blue");
}
{
REQUIRE_FALSE(color_type.value_to_name(100500));
REQUIRE_FALSE(color_type.value_to_name(color{100500}));
}
CHECK(color_type.value_to_name(100500).empty());
CHECK(color_type.value_to_name(color{100500}).empty());
}
SUBCASE("ecolor/value_to_name") {
const meta::enum_type ecolor_type = meta::resolve_type<ecolor>();
REQUIRE(ecolor_type);
{
REQUIRE(ecolor_type.value_to_name(ecolor_red));
CHECK(ecolor_type.value_to_name(ecolor_red) == "red");
}
{
REQUIRE(ecolor_type.value_to_name(meta::value{ecolor_blue}));
CHECK(ecolor_type.value_to_name(ecolor_blue) == "blue");
}
{
REQUIRE_FALSE(ecolor_type.value_to_name(100500));
REQUIRE_FALSE(ecolor_type.value_to_name(ecolor{100500}));
}
CHECK(ecolor_type.value_to_name(meta::value{ecolor_blue}) == "blue");
CHECK(ecolor_type.value_to_name(100500).empty());
CHECK(ecolor_type.value_to_name(ecolor{100500}).empty());
}
SUBCASE("color/name_to_value") {