Pass serial::pad by-value
This commit is contained in:
parent
fece9f51a4
commit
d889dd9b7d
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue