raw: Make it possible to override alignment checks
Change-Id: I4de0d28007ea914d9d5eb9ac5f64132a57021409
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/stdplus/raw.hpp b/include/stdplus/raw.hpp
index 5ac2a2f..c572744 100644
--- a/include/stdplus/raw.hpp
+++ b/include/stdplus/raw.hpp
@@ -91,19 +91,30 @@
STDPLUS_COPY_FROM(copyFromStrict, !=)
#undef STDPLUS_COPY_FROM
+/** @brief If you can guarantee the underlying data is properly aligned
+ * for raw struct access this specifier is used to override compile checks. */
+struct Aligned
+{
+};
+struct UnAligned
+{
+};
+
/** @brief References the data from a buffer if aligned
*
* @param[in] data - The data buffer being referenced
* @return The reference to the data in the new type
*/
#define STDPLUS_REF_FROM(func, comp) \
- template <typename T, typename Container, \
+ template <typename T, typename A = stdplus::raw::UnAligned, \
+ typename Container, \
typename Tp = detail::copyConst<T, detail::dataType<Container>>> \
inline constexpr Tp& func(Container&& c) \
{ \
static_assert(std::is_trivially_copyable_v<Tp>); \
static_assert(detail::trivialContainer<Container>); \
- static_assert(sizeof(*std::data(c)) % alignof(Tp) == 0); \
+ static_assert(std::is_same_v<A, Aligned> || \
+ sizeof(*std::data(c)) % alignof(Tp) == 0); \
const size_t bytes = std::size(c) * sizeof(*std::data(c)); \
if (bytes comp sizeof(Tp)) \
{ \
@@ -146,20 +157,20 @@
* @param[in,out] data - The data buffer being extracted from
* @return A reference to the data
*/
-template <typename T, typename CharT>
+template <typename T, typename A = stdplus::raw::UnAligned, typename CharT>
inline constexpr const T& extractRef(std::basic_string_view<CharT>& data)
{
- const T& ret = refFrom<T>(data);
+ const T& ret = refFrom<T, A>(data);
static_assert(sizeof(T) % sizeof(CharT) == 0);
data.remove_prefix(sizeof(T) / sizeof(CharT));
return ret;
}
-template <typename T, typename IntT,
+template <typename T, typename A = stdplus::raw::UnAligned, typename IntT,
typename = std::enable_if_t<std::is_trivially_copyable_v<IntT>>,
typename Tp = detail::copyConst<T, IntT>>
inline constexpr Tp& extractRef(std::span<IntT>& data)
{
- Tp& ret = refFrom<Tp>(data);
+ Tp& ret = refFrom<Tp, A>(data);
static_assert(sizeof(Tp) % sizeof(IntT) == 0);
data = data.subspan(sizeof(Tp) / sizeof(IntT));
return ret;