Skip to content

Commit

Permalink
Add OZO_STRONG_TYPEDEF macro instead of BOOS_FUSION_TYPEDEF
Browse files Browse the repository at this point in the history
  • Loading branch information
thed636 committed Sep 19, 2018
1 parent 79e649c commit 76d29d2
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 31 deletions.
1 change: 0 additions & 1 deletion benchmarks/ozo_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <boost/asio/spawn.hpp>

#include <iostream>
#include <optional>

int main(int argc, char *argv[]) {
using namespace ozo::literals;
Expand Down
17 changes: 5 additions & 12 deletions include/ozo/binary_deserialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,12 @@ struct recv_impl<std::vector<T, Alloc>, Require<!std::is_same_v<T, char>>> {
}
};

template <>
struct recv_impl<pg::name> {
template <typename T, typename Tag>
struct recv_impl<detail::strong_typedef_wrapper<T, Tag>> {
using out_type = detail::strong_typedef_wrapper<T, Tag>;
template <typename M>
static istream& apply(istream& in, int32_t size, const oid_map_t<M>& oid_map, pg::name& out) {
return recv_impl<std::string>::apply(in, size, oid_map, out);
}
};

template <>
struct recv_impl<pg::bytea> {
template <typename M>
static istream& apply(istream& in, int32_t size, const oid_map_t<M>& oid_map, pg::bytea& out) {
return recv_impl<std::vector<char>>::apply(in, size, oid_map, out);
static istream& apply(istream& in, int32_t size, const oid_map_t<M>& oid_map, out_type& out) {
return recv_impl<typename out_type::base_type>::apply(in, size, oid_map, out);
}
};

Expand Down
18 changes: 5 additions & 13 deletions include/ozo/binary_serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,12 @@ struct send_impl<std::vector<T, Alloc>, Require<!std::is_same_v<T, char>>> {
}
};

template <>
struct send_impl<pg::name> {
template <typename T, typename Tag>
struct send_impl<detail::strong_typedef_wrapper<T, Tag>> {
using in_type = detail::strong_typedef_wrapper<T, Tag>;
template <typename M>
static ostream& apply(ostream& out, const oid_map_t<M>& map, const pg::name& in) {
return send_impl<std::string>::apply(out, map, in);
}
};


template <>
struct send_impl<pg::bytea> {
template <typename M>
static ostream& apply(ostream& out, const oid_map_t<M>& map, const pg::name& in) {
return send_impl<std::vector<char>>::apply(out, map, in);
static ostream& apply(ostream& out, const oid_map_t<M>& map, const in_type& in) {
return send_impl<typename in_type::base_type>::apply(out, map, in);
}
};

Expand Down
101 changes: 101 additions & 0 deletions include/ozo/detail/strong_typedef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include <boost/operators.hpp>
#include <type_traits>

namespace ozo::detail {

template <typename T, typename Tag>
class strong_typedef_wrapper
: boost::totally_ordered1<strong_typedef_wrapper<T, Tag>
, boost::totally_ordered2<strong_typedef_wrapper<T, Tag>, 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 <typename T>
struct is_strong_typedef : std::false_type {};

template <typename T, typename Tag>
struct is_strong_typedef<strong_typedef_wrapper<T, Tag>> : std::true_type {};

template <typename T>
constexpr auto StrongTypedef = is_strong_typedef<std::decay_t<T>>::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<char>, bytes)
}
// Types are completely different
static_assert(!std::is_same_v<std::vector<char>, demo::bytes>);
// Type bytes::base_type is same as a first argument of the macro
static_assert(std::is_same_v<std::vector<char>, demo::bytes::base_type>);
demo::bytes b{};
std::vector<char>& 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<base, type##_strong_typedef_tag>;
#endif
6 changes: 3 additions & 3 deletions include/ozo/type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <ozo/detail/pg_type.h>
#include <ozo/detail/float.h>
#include <ozo/detail/strong_typedef.h>

#include <libpq-fe.h>

Expand All @@ -17,7 +18,6 @@
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/serialization/strong_typedef.hpp>

// Fusion adaptors support
#include <boost/fusion/support/is_sequence.hpp>
Expand Down Expand Up @@ -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<char>, bytea)
OZO_STRONG_TYPEDEF(std::string, name)
OZO_STRONG_TYPEDEF(std::vector<char>, bytea)

} // namespace pg
} // namespace ozo
Expand Down
3 changes: 1 addition & 2 deletions tests/binary_deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<char>& 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) {
Expand Down

0 comments on commit 76d29d2

Please sign in to comment.