From 76d29d24f0a1bc72004b490fac5f20bb5833c002 Mon Sep 17 00:00:00 2001 From: "Sergei L. Khandrikov" Date: Mon, 17 Sep 2018 00:05:03 +0300 Subject: [PATCH] Add OZO_STRONG_TYPEDEF macro instead of BOOS_FUSION_TYPEDEF --- benchmarks/ozo_benchmark.cpp | 1 - include/ozo/binary_deserialization.h | 17 ++--- include/ozo/binary_serialization.h | 18 ++--- include/ozo/detail/strong_typedef.h | 101 +++++++++++++++++++++++++++ include/ozo/type_traits.h | 6 +- tests/binary_deserialization.cpp | 3 +- 6 files changed, 115 insertions(+), 31 deletions(-) create mode 100644 include/ozo/detail/strong_typedef.h diff --git a/benchmarks/ozo_benchmark.cpp b/benchmarks/ozo_benchmark.cpp index b6fa55fd2..763896d6b 100644 --- a/benchmarks/ozo_benchmark.cpp +++ b/benchmarks/ozo_benchmark.cpp @@ -8,7 +8,6 @@ #include #include -#include int main(int argc, char *argv[]) { using namespace ozo::literals; diff --git a/include/ozo/binary_deserialization.h b/include/ozo/binary_deserialization.h index a1ca41256..7343b8422 100644 --- a/include/ozo/binary_deserialization.h +++ b/include/ozo/binary_deserialization.h @@ -126,19 +126,12 @@ struct recv_impl, Require>> { } }; -template <> -struct recv_impl { +template +struct recv_impl> { + using out_type = detail::strong_typedef_wrapper; template - static istream& apply(istream& in, int32_t size, const oid_map_t& oid_map, pg::name& out) { - return recv_impl::apply(in, size, oid_map, out); - } -}; - -template <> -struct recv_impl { - template - static istream& apply(istream& in, int32_t size, const oid_map_t& oid_map, pg::bytea& out) { - return recv_impl>::apply(in, size, oid_map, out); + static istream& apply(istream& in, int32_t size, const oid_map_t& oid_map, out_type& out) { + return recv_impl::apply(in, size, oid_map, out); } }; diff --git a/include/ozo/binary_serialization.h b/include/ozo/binary_serialization.h index 18e290062..388d03179 100644 --- a/include/ozo/binary_serialization.h +++ b/include/ozo/binary_serialization.h @@ -40,20 +40,12 @@ struct send_impl, Require>> { } }; -template <> -struct send_impl { +template +struct send_impl> { + using in_type = detail::strong_typedef_wrapper; template - static ostream& apply(ostream& out, const oid_map_t& map, const pg::name& in) { - return send_impl::apply(out, map, in); - } -}; - - -template <> -struct send_impl { - template - static ostream& apply(ostream& out, const oid_map_t& map, const pg::name& in) { - return send_impl>::apply(out, map, in); + static ostream& apply(ostream& out, const oid_map_t& map, const in_type& in) { + return send_impl::apply(out, map, in); } }; diff --git a/include/ozo/detail/strong_typedef.h b/include/ozo/detail/strong_typedef.h new file mode 100644 index 000000000..ce06ac720 --- /dev/null +++ b/include/ozo/detail/strong_typedef.h @@ -0,0 +1,101 @@ +#include +#include + +namespace ozo::detail { + +template +class strong_typedef_wrapper + : boost::totally_ordered1 + , boost::totally_ordered2, T>> { + + T base_; +public: + using base_type = T; + + explicit strong_typedef_wrapper(const base_type& v) noexcept(noexcept(base_type(v))) + : base_(v) {} + explicit strong_typedef_wrapper(base_type&& v) noexcept(noexcept(base_type(v))) + : base_(v) {} + + strong_typedef_wrapper() = default; + strong_typedef_wrapper(const strong_typedef_wrapper&) = default; + strong_typedef_wrapper(strong_typedef_wrapper&&) = default; + + strong_typedef_wrapper& operator = (const strong_typedef_wrapper&) = default; + strong_typedef_wrapper& operator = (strong_typedef_wrapper&&) = default; + + strong_typedef_wrapper& operator = (const base_type& rhs) noexcept(noexcept(base_ = rhs)) { + base_ = rhs; + return *this; + } + + strong_typedef_wrapper& operator = (base_type&& rhs) noexcept(noexcept(base_ = std::move(rhs))) { + base_ = std::move(rhs); + return *this; + } + + constexpr const base_type& get() const & noexcept { return base_;} + constexpr base_type& get() & noexcept { return base_;} + constexpr base_type&& get() && noexcept { return std::move(base_);} + + operator const base_type&() const & noexcept {return get();} + operator base_type&() & noexcept {return get();} + operator base_type&&() && noexcept {return get();} + + bool operator == (const strong_typedef_wrapper& rhs) const {return base_ == rhs.base_;} + bool operator < (const strong_typedef_wrapper& rhs) const {return base_ < rhs.base_;} +}; + +template +struct is_strong_typedef : std::false_type {}; + +template +struct is_strong_typedef> : std::true_type {}; + +template +constexpr auto StrongTypedef = is_strong_typedef>::value; + +} // namespace ozo::detail + +/** + * @brief Strong typedef + * @ingroup group-type_system + * + * C++ `typedef` creates only an alias to a base type, so the both types are the same. + * To get a really new type it is necessary to make some boilerplate code. + * This macro do such work. It is very similar to `BOOST_STRONG_TYPEDEF` + * Except the new type has `base_type` type and `get()` method which provides + * access to underlying base type object. + * @note This macro may be used inside a namespace. + * @param base --- base type + * @param type --- new type + * + * ### Example + * + * @code + +namespace demo { + +OZO_STRONG_TYPEDEF(std::vector, bytes) + +} +// Types are completely different +static_assert(!std::is_same_v, demo::bytes>); +// Type bytes::base_type is same as a first argument of the macro +static_assert(std::is_same_v, demo::bytes::base_type>); + +demo::bytes b{}; +std::vector& base(b); + +// Member function bytes::get() provides access to the underlying +// base type object +assert(std::addressof(base) == std::addressof(b.get())); + * @endcode + */ +#ifdef OZO_DOCUMENTATION +#define OZO_STRONG_TYPEDEF(base, type) +#else +#define OZO_STRONG_TYPEDEF(base, type)\ + struct type##_strong_typedef_tag;\ + using type = ozo::detail::strong_typedef_wrapper; +#endif diff --git a/include/ozo/type_traits.h b/include/ozo/type_traits.h index 0c30f449a..ddc76d4c5 100644 --- a/include/ozo/type_traits.h +++ b/include/ozo/type_traits.h @@ -2,6 +2,7 @@ #include #include +#include #include @@ -17,7 +18,6 @@ #include #include #include -#include // Fusion adaptors support #include @@ -387,8 +387,8 @@ constexpr auto size_of(const T& v) noexcept -> typename std::enable_if< */ namespace pg { -BOOST_STRONG_TYPEDEF(std::string, name) -BOOST_STRONG_TYPEDEF(std::vector, bytea) +OZO_STRONG_TYPEDEF(std::string, name) +OZO_STRONG_TYPEDEF(std::vector, bytea) } // namespace pg } // namespace ozo diff --git a/tests/binary_deserialization.cpp b/tests/binary_deserialization.cpp index 9758867ec..a0b79826b 100644 --- a/tests/binary_deserialization.cpp +++ b/tests/binary_deserialization.cpp @@ -125,8 +125,7 @@ TEST_F(recv, should_convert_BYTEAOID_to_pg_bytea) { ozo::pg::bytea got; ozo::recv(value, oid_map, got); - std::vector& underlying = got; - EXPECT_EQ("test", std::string_view(std::data(underlying), std::size(underlying))); + EXPECT_EQ("test", std::string_view(std::data(got.get()), std::size(got.get()))); } TEST_F(recv, should_convert_TEXTOID_to_std_string) {