From ff250cd7acd3bbaa2d6038da4750977e5cdd1e42 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Sun, 18 Dec 2022 14:20:36 +0800 Subject: [PATCH] upd: [imp] optimize `result` --- include/libimp/generic.h | 20 ++++++ include/libimp/result.h | 103 +++++++++++++++-------------- src/libipc/platform/win/shm_impl.h | 2 +- test/imp/test_imp_result.cpp | 5 ++ 4 files changed, 79 insertions(+), 51 deletions(-) diff --git a/include/libimp/generic.h b/include/libimp/generic.h index 80932ac..6ef0913 100644 --- a/include/libimp/generic.h +++ b/include/libimp/generic.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include "libimp/def.h" @@ -40,4 +41,23 @@ struct tag_invoke_t { constexpr detail::tag_invoke_t tag_invoke {}; +/** + * @brief Circumventing forwarding reference may override copy and move constructs. + * @see https://mpark.github.io/programming/2014/06/07/beware-of-perfect-forwarding-constructors/ + */ +namespace detail { + +template +struct is_same_first : std::false_type {}; + +template +struct is_same_first : std::true_type {}; + +} // namespace detail + +template +using is_not_match = + typename std::enable_if::type...>::value>::type; + LIBIMP_NAMESPACE_END_ diff --git a/include/libimp/result.h b/include/libimp/result.h index 4aa8735..5ab78a7 100644 --- a/include/libimp/result.h +++ b/include/libimp/result.h @@ -14,6 +14,7 @@ #include "libimp/detect_plat.h" #include "libimp/export.h" #include "libimp/fmt.h" +#include "libimp/generic.h" LIBIMP_NAMESPACE_BEG_ @@ -54,22 +55,35 @@ struct default_traits; } // namespace detail_result template , - typename = void> + typename TypeTraits = detail_result::default_traits> class result; namespace detail_result { template struct default_traits::value>> { - constexpr static T value() noexcept { return 0; } + /// @brief Custom initialization. + constexpr static void init_code(result_code &code) noexcept { + code = {}; + } + constexpr static void init_code(result_code &code, bool ok, T value) noexcept { + code = {ok, static_cast(value)}; + } + constexpr static void init_code(result_code &code, T value) noexcept { + init_code(code, true, value); + } - static result_type cast_to_code(T value) noexcept { - return static_cast(value); + /// @brief Custom default value. + constexpr static T default_value() noexcept { + return 0; } - static T cast_from_code(result_type code) noexcept { - return static_cast(code); + + /// @brief Custom type conversions. + constexpr static T cast_from_code(result_code code) noexcept { + return static_cast(code.value()); } + + /// @brief Custom formatted output. static std::string format(result const &r) noexcept { return fmt(*r); } @@ -77,14 +91,28 @@ struct default_traits::value>> { template struct default_traits::value>> { - constexpr static T value() noexcept { return nullptr; } + /// @brief Custom initialization. + constexpr static void init_code(result_code &code, T value = default_value()) noexcept { + code = {default_value() != value, reinterpret_cast(value)}; + } + constexpr static void init_code(result_code &code, std::nullptr_t) noexcept { + code = {false, {}}; + } + constexpr static void init_code(result_code &code, std::nullptr_t, result_type r) noexcept { + code = {false, r}; + } - static result_type cast_to_code(T value) noexcept { - return reinterpret_cast(value); + /// @brief Custom default value. + constexpr static T default_value() noexcept { + return nullptr; } - static T cast_from_code(result_type code) noexcept { - return reinterpret_cast(code); + + /// @brief Custom type conversions. + constexpr static T cast_from_code(result_code code) noexcept { + return code.ok() ? reinterpret_cast(code.value()) : default_value(); } + + /// @brief Custom formatted output. static std::string format(result const &r) noexcept { if LIBIMP_LIKELY(r) { return fmt(static_cast(*r)); @@ -95,53 +123,28 @@ struct default_traits::value>> { } // namespace detail_result -template -class result::value>> { +template +class result : public TypeTraits { + /// @brief Internal data is stored using result_code. result_code code_; public: - using default_traits_t = DefTraits; + using type_traits_t = TypeTraits; result() noexcept = default; - result(T value) noexcept - : result(true, std::move(value)) {} - - result(bool ok, T value) noexcept - : code_(ok, default_traits_t::cast_to_code(value)) {} - - T value() const noexcept { return default_traits_t::cast_from_code(code_.value()); } - bool ok() const noexcept { return code_.ok(); } - - T operator*() const noexcept { - return value(); - } - explicit operator bool() const noexcept { - return ok(); + template , + typename = decltype(type_traits_t::init_code(std::declval() + , std::declval()...))> + result(A &&... args) noexcept { + type_traits_t::init_code(code_, std::forward(args)...); } - friend bool operator==(result const &lhs, result const &rhs) noexcept { return lhs.code_ == rhs.code_; } - friend bool operator!=(result const &lhs, result const &rhs) noexcept { return lhs.code_ != rhs.code_; } -}; - -template -class result::value>> { - - result_code code_; - -public: - using default_traits_t = DefTraits; - - result(T value = default_traits_t::value()) noexcept - : code_(default_traits_t::value() != value, - default_traits_t::cast_to_code(value)) {} - - result(std::nullptr_t, result_type code) noexcept - : code_(false, code) {} - - T value() const noexcept { return code_.ok() ? default_traits_t::cast_from_code(code_.value()) : nullptr; } bool ok() const noexcept { return code_.ok(); } + T value() const noexcept { return type_traits_t::cast_from_code(code_); } + result_type code_value() const noexcept { return code_.value(); } T operator*() const noexcept { @@ -164,7 +167,7 @@ inline bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, result_code template bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, result r) { - return fmt_to(ctx, "[", (r ? "succ" : "fail"), ", value = ", result::default_traits_t::format(r), "]"); + return fmt_to(ctx, "[", (r ? "succ" : "fail"), ", value = ", result::type_traits_t::format(r), "]"); } } // namespace detail diff --git a/src/libipc/platform/win/shm_impl.h b/src/libipc/platform/win/shm_impl.h index 897d94b..4442d70 100644 --- a/src/libipc/platform/win/shm_impl.h +++ b/src/libipc/platform/win/shm_impl.h @@ -20,7 +20,7 @@ using namespace ::LIBIMP; result shm_open(std::string name, std::size_t size, mode::type type) noexcept { LIBIMP_LOG_(); auto h = mmap_open(name, size, type); - if (h == NULL) { + if (*h == NULL) { log.error("failed: mmap_open(name = ", name, ", size = ", size, ", type = ", type, ")."); return {nullptr, h.code_value()}; } diff --git a/test/imp/test_imp_result.cpp b/test/imp/test_imp_result.cpp index 162264c..99ed748 100644 --- a/test/imp/test_imp_result.cpp +++ b/test/imp/test_imp_result.cpp @@ -21,6 +21,11 @@ TEST(result, ok) { EXPECT_FALSE(ret); EXPECT_FALSE(ret.ok()); EXPECT_EQ(*ret, 1234); + + imp::result r2 {nullptr, 4321}; + EXPECT_NE(r2, nullptr); // imp::result{nullptr} + EXPECT_EQ(*r2, nullptr); + EXPECT_FALSE(r2); } TEST(result, code) {