Pass serial::pad by-value

This commit is contained in:
Kp 2014-09-20 22:44:46 +00:00
parent fece9f51a4
commit d889dd9b7d

View file

@ -93,9 +93,6 @@ class class_type;
template <typename>
class array_type;
template <typename>
class unhandled_type;
struct endian_access
{
/*
@ -118,6 +115,63 @@ struct endian_access
/* Implementation details - avoid namespace pollution */
namespace detail {
/*
* gcc before 4.8 chokes on tuple<tuple<struct {}>> due to ambiguous
* base class after applying EBO
*/
template <typename T>
class wrapped_empty_value : T
{
public:
wrapped_empty_value() = default;
wrapped_empty_value(T &&t) : T(std::forward<T>(t)) {}
T &get() { return *this; }
const T &get() const { return *this; }
};
template <typename T>
static inline T &extract_value(wrapped_empty_value<T> &t)
{
return t.get();
}
template <typename T>
static inline const T &extract_value(const wrapped_empty_value<T> &t)
{
return t.get();
}
template <typename T, typename Trr = typename tt::remove_reference<T>::type>
struct capture_type
{
typedef
typename tt::conditional<tt::is_lvalue_reference<T>::value,
std::reference_wrapper<Trr>,
typename tt::conditional<tt::is_empty<Trr>::value,
wrapped_empty_value<Trr>,
std::tuple<Trr>
>::type
>::type type;
};
template <typename T, typename Trr = typename tt::remove_reference<T>::type>
static inline auto capture_value(Trr &t) -> decltype(std::ref(t))
{
return std::ref(t);
}
template <typename T, typename Trr = typename tt::remove_reference<T>::type>
static inline typename tt::enable_if<tt::is_empty<Trr>::value, detail::wrapped_empty_value<Trr>>::type capture_value(Trr &&t)
{
return std::forward<Trr>(t);
}
template <typename T, typename Trr = typename tt::remove_reference<T>::type>
static inline typename tt::enable_if<!tt::is_empty<Trr>::value && tt::is_rvalue_reference<T>::value, std::tuple<Trr>>::type capture_value(Trr &&t)
{
return std::tuple<Trr>{std::forward<T>(t)};
}
template <std::size_t amount, uint8_t value>
class pad_type
{
@ -222,13 +276,30 @@ static inline void process_udt(Accessor &accessor, const pad_type<amount, value>
static inline void sequence(std::initializer_list<uint8_t>) {}
template <typename T>
static inline T &extract_value(std::reference_wrapper<T> t)
{
return t;
}
template <typename T>
static inline T &extract_value(std::tuple<T> &t)
{
return std::get<0>(t);
}
template <typename T>
static inline const T &extract_value(const std::tuple<T> &t)
{
return std::get<0>(t);
}
}
template <std::size_t amount, uint8_t value = 0xcc>
static inline const detail::pad_type<amount, value> &pad()
static inline detail::pad_type<amount, value> pad()
{
static const detail::pad_type<amount, value> p{};
return p;
return {};
}
#define DEFINE_SERIAL_UDT_TO_MESSAGE(TYPE, NAME, MEMBERLIST) \
@ -248,28 +319,28 @@ static inline const detail::pad_type<amount, value> &pad()
#define ASSERT_SERIAL_UDT_MESSAGE_SIZE(T, SIZE) \
assert_equal(serial::class_type<T>::maximum_size, SIZE, "sizeof(" #T ") is not " #SIZE)
template <typename M1, typename T1>
class udt_message_compatible_same_type : public tt::integral_constant<bool, tt::is_same<typename tt::remove_const<M1>::type, T1>::value>
template <typename M1, typename T1, typename M1rcv_rr = typename tt::remove_cv<typename tt::remove_reference<M1>::type>::type>
struct udt_message_compatible_same_type : tt::is_same<M1rcv_rr, T1>
{
static_assert(tt::is_same<typename tt::remove_const<M1>::type, T1>::value, "parameter type mismatch");
static_assert(tt::is_same<M1rcv_rr, T1>::value, "parameter type mismatch");
};
template <bool, typename M, typename T>
class assert_udt_message_compatible2;
template <typename M, typename T>
class assert_udt_message_compatible2<false, M, T> : public tt::integral_constant<bool, false>
struct assert_udt_message_compatible2<false, M, T> : tt::false_type
{
};
template <typename M1, typename T1>
class assert_udt_message_compatible2<true, message<M1>, std::tuple<T1>> : public udt_message_compatible_same_type<M1, T1>
struct assert_udt_message_compatible2<true, message<M1>, std::tuple<T1>> : udt_message_compatible_same_type<M1, T1>
{
};
template <typename M1, typename M2, typename... Mn, typename T1, typename T2, typename... Tn>
class assert_udt_message_compatible2<true, message<M1, M2, Mn...>, std::tuple<T1, T2, Tn...>> :
public tt::integral_constant<bool, assert_udt_message_compatible2<udt_message_compatible_same_type<M1, T1>::value, message<M2, Mn...>, std::tuple<T2, Tn...>>::value>
struct assert_udt_message_compatible2<true, message<M1, M2, Mn...>, std::tuple<T1, T2, Tn...>> :
assert_udt_message_compatible2<udt_message_compatible_same_type<M1, T1>::value, message<M2, Mn...>, std::tuple<T2, Tn...>>
{
};
@ -277,19 +348,17 @@ template <typename M, typename T>
class assert_udt_message_compatible1;
template <typename M1, typename... Mn, typename T1, typename... Tn>
class assert_udt_message_compatible1<message<M1, Mn...>, std::tuple<T1, Tn...>> : public tt::integral_constant<bool, assert_udt_message_compatible2<sizeof...(Mn) == sizeof...(Tn), message<M1, Mn...>, std::tuple<T1, Tn...>>::value>
struct assert_udt_message_compatible1<message<M1, Mn...>, std::tuple<T1, Tn...>> : assert_udt_message_compatible2<sizeof...(Mn) == sizeof...(Tn), message<M1, Mn...>, std::tuple<T1, Tn...>>
{
static_assert(sizeof...(Mn) <= sizeof...(Tn), "too few types in tuple");
static_assert(sizeof...(Mn) >= sizeof...(Tn), "too few types in message");
};
template <typename, typename>
class assert_udt_message_compatible
{
};
class assert_udt_message_compatible;
template <typename C, typename T1, typename... Tn>
class assert_udt_message_compatible<C, std::tuple<T1, Tn...>> : public tt::integral_constant<bool, assert_udt_message_compatible1<typename class_type<C>::message, std::tuple<T1, Tn...>>::value>
struct assert_udt_message_compatible<C, std::tuple<T1, Tn...>> : assert_udt_message_compatible1<typename class_type<C>::as_message, std::tuple<T1, Tn...>>
{
};
@ -362,9 +431,10 @@ protected:
};
template <typename T>
class message_type : message_dispatch_type<T>
class message_type : message_dispatch_type<typename tt::remove_reference<T>::type>
{
typedef typename message_dispatch_type<T>::effective_type effective_type;
typedef message_dispatch_type<typename tt::remove_reference<T>::type> base_type;
typedef typename base_type::effective_type effective_type;
public:
static const std::size_t maximum_size = effective_type::maximum_size;
};
@ -374,13 +444,13 @@ class message_dispatch_type<message<A1>, void>
{
protected:
typedef message_type<A1> effective_type;
public:
typedef message<A1> as_message;
};
template <typename T>
class class_type : public message_type<decltype(udt_to_message(*(T*)0))>
class class_type : public message_type<decltype(udt_to_message(std::forward<T>(*static_cast<T*>(nullptr))))>
{
public:
typedef decltype(udt_to_message(*(T*)0)) message;
};
template <typename T, std::size_t N>
@ -399,13 +469,14 @@ template <typename A1, typename A2, typename... Args>
class message_type<message<A1, A2, Args...>>
{
public:
typedef message<A1, A2, Args...> as_message;
static const std::size_t maximum_size = message_type<A1>::maximum_size + message_type<message<A2, Args...>>::maximum_size;
};
template <typename A1, typename... Args>
class message
{
typedef std::tuple<typename tt::add_pointer<A1>::type, typename tt::add_pointer<Args>::type...> tuple_type;
typedef std::tuple<typename detail::capture_type<A1 &&>::type, typename detail::capture_type<Args &&>::type...> tuple_type;
template <typename T1>
static void check_type()
{
@ -418,9 +489,8 @@ class message
}
tuple_type t;
public:
typedef A1 head_type;
message(A1 &a1, Args&... args) :
t(addressof(a1), addressof(args)...)
message(A1 &&a1, Args &&... args) :
t(detail::capture_value<A1>(std::forward<A1>(a1)), detail::capture_value<Args>(std::forward<Args>(args))...)
{
check_types();
}
@ -431,9 +501,9 @@ public:
};
template <typename A1, typename... Args>
static inline message<A1, Args...> make_message(A1 &a1, Args&... args)
static inline message<A1 &&, Args &&...> make_message(A1 &&a1, Args &&... args)
{
return message<A1, Args...>(a1, std::forward<Args&>(args)...);
return {std::forward<A1>(a1), std::forward<Args>(args)...};
}
#define SERIAL_DEFINE_SIZE_SPECIFIC_USWAP_BUILTIN(HBITS,BITS) \
@ -629,7 +699,7 @@ typename tt::enable_if<is_cxx_array<A1>::value, void>::type process_buffer(Acces
template <typename Accessor, typename... Args, std::size_t... N>
static inline void process_message_tuple(Accessor &accessor, const std::tuple<Args...> &t, index_sequence<N...>)
{
detail::sequence({(process_buffer(accessor, *std::get<N>(t)), static_cast<uint8_t>(0))...});
detail::sequence({(process_buffer(accessor, detail::extract_value(std::get<N>(t))), static_cast<uint8_t>(0))...});
}
template <typename Accessor, typename A1, typename... Args>