raw: Use concepts

Change-Id: I248cc92464cdffa45fe5af831747b31680acb06c
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/stdplus/concepts.hpp b/include/stdplus/concepts.hpp
index 41373f6..ce020a6 100644
--- a/include/stdplus/concepts.hpp
+++ b/include/stdplus/concepts.hpp
@@ -22,4 +22,7 @@
                                            } -> std::convertible_to<bool>;
                                        };
 
-}
+template <typename T>
+concept TriviallyCopyable = std::is_trivially_copyable_v<T>;
+
+} // namespace stdplus
diff --git a/include/stdplus/raw.hpp b/include/stdplus/raw.hpp
index 21dc728..4f6c076 100644
--- a/include/stdplus/raw.hpp
+++ b/include/stdplus/raw.hpp
@@ -1,6 +1,8 @@
 #pragma once
 #include <fmt/format.h>
 
+#include <stdplus/concepts.hpp>
+
 #include <algorithm>
 #include <span>
 #include <stdexcept>
@@ -30,7 +32,7 @@
 /** @brief Determines if the container holds trivially copyable data
  */
 template <typename Container>
-inline constexpr bool trivialContainer =
+inline constexpr bool containsTrivial =
     std::is_trivially_copyable_v<dataType<Container>>;
 
 /** @brief Adds const to A if B is const
@@ -46,6 +48,11 @@
 template <typename T>
 inline constexpr bool hasData<T, std::void_t<dataType<T>, sizeType<T>>> = true;
 
+template <typename T>
+concept ContainsTrivial = hasData<T> && containsTrivial<T>;
+template <typename T>
+concept NotContainerTrivial = !hasData<T> && TriviallyCopyable<T>;
+
 } // namespace detail
 
 /** @brief Compares two containers to see if their raw bytes are equal
@@ -54,11 +61,9 @@
  *  @param[in] b - The second container
  *  @return True if they are the same, false otherwise
  */
-template <typename A, typename B>
+template <TriviallyCopyable A, TriviallyCopyable B>
 constexpr bool equal(const A& a, const B& b) noexcept
 {
-    static_assert(std::is_trivially_copyable_v<A>);
-    static_assert(std::is_trivially_copyable_v<B>);
     static_assert(sizeof(A) == sizeof(B));
     const auto a_byte = reinterpret_cast<const std::byte*>(&a);
     const auto b_byte = reinterpret_cast<const std::byte*>(&b);
@@ -71,11 +76,9 @@
  *  @return The copyable type with data populated
  */
 #define STDPLUS_COPY_FROM(func, comp)                                          \
-    template <typename T, typename Container>                                  \
+    template <TriviallyCopyable T, detail::ContainsTrivial Container>          \
     constexpr T func(const Container& c)                                       \
     {                                                                          \
-        static_assert(std::is_trivially_copyable_v<T>);                        \
-        static_assert(detail::trivialContainer<Container>);                    \
         T ret;                                                                 \
         const size_t bytes = std::size(c) * sizeof(*std::data(c));             \
         if (bytes comp sizeof(ret))                                            \
@@ -105,13 +108,11 @@
  *  @return The reference to the data in the new type
  */
 #define STDPLUS_REF_FROM(func, comp)                                           \
-    template <typename T, typename A = stdplus::raw::UnAligned,                \
-              typename Container,                                              \
+    template <TriviallyCopyable T, typename A = stdplus::raw::UnAligned,       \
+              detail::ContainsTrivial Container,                               \
               typename Tp = detail::copyConst<T, detail::dataType<Container>>> \
     constexpr Tp& func(Container&& c)                                          \
     {                                                                          \
-        static_assert(std::is_trivially_copyable_v<Tp>);                       \
-        static_assert(detail::trivialContainer<Container>);                    \
         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));             \
@@ -140,8 +141,7 @@
     data.remove_prefix(sizeof(T) / sizeof(CharT));
     return ret;
 }
-template <typename T, typename IntT,
-          typename = std::enable_if_t<std::is_trivially_copyable_v<IntT>>>
+template <typename T, TriviallyCopyable IntT>
 constexpr T extract(std::span<IntT>& data)
 {
     T ret = copyFrom<T>(data);
@@ -164,9 +164,8 @@
     data.remove_prefix(sizeof(T) / sizeof(CharT));
     return ret;
 }
-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>>
+template <typename T, typename A = stdplus::raw::UnAligned,
+          TriviallyCopyable IntT, typename Tp = detail::copyConst<T, IntT>>
 constexpr Tp& extractRef(std::span<IntT>& data)
 {
     Tp& ret = refFrom<Tp, A>(data);
@@ -181,43 +180,32 @@
  *  @param[in] t - The trivial raw data
  *  @return A view over the input with the given output integral type
  */
-template <typename CharT, typename T>
-constexpr std::enable_if_t<!detail::hasData<T>, std::basic_string_view<CharT>>
-    asView(const T& t) noexcept
+template <typename CharT, detail::NotContainerTrivial T>
+constexpr std::basic_string_view<CharT> asView(const T& t) noexcept
 {
-    static_assert(std::is_trivially_copyable_v<T>);
     static_assert(sizeof(T) % sizeof(CharT) == 0);
     return {reinterpret_cast<const CharT*>(&t), sizeof(T) / sizeof(CharT)};
 }
 
-template <typename CharT, typename Container>
-constexpr std::enable_if_t<detail::hasData<Container>,
-                           std::basic_string_view<CharT>>
-    asView(const Container& c) noexcept
+template <typename CharT, detail::ContainsTrivial Container>
+constexpr std::basic_string_view<CharT> asView(const Container& c) noexcept
 {
-    static_assert(detail::trivialContainer<Container>);
     static_assert(sizeof(*std::data(c)) % sizeof(CharT) == 0);
     return {reinterpret_cast<const CharT*>(std::data(c)),
             std::size(c) * sizeof(*std::data(c)) / sizeof(CharT)};
 }
 
-template <typename IntT, typename T,
-          typename = std::enable_if_t<std::is_trivially_copyable_v<IntT>>,
-          typename = std::enable_if_t<!detail::hasData<T>>,
+template <TriviallyCopyable IntT, detail::NotContainerTrivial T,
           typename IntTp = detail::copyConst<IntT, T>>
 constexpr std::span<IntTp> asSpan(T& t) noexcept
 {
-    static_assert(std::is_trivially_copyable_v<T>);
     static_assert(sizeof(T) % sizeof(IntTp) == 0);
     return {reinterpret_cast<IntTp*>(&t), sizeof(T) / sizeof(IntTp)};
 }
-template <typename IntT, typename Container,
-          typename = std::enable_if_t<std::is_trivially_copyable_v<IntT>>,
-          typename = std::enable_if_t<detail::hasData<Container>>,
+template <TriviallyCopyable IntT, detail::ContainsTrivial Container,
           typename IntTp = detail::copyConst<IntT, detail::dataType<Container>>>
 constexpr std::span<IntTp> asSpan(Container&& c) noexcept
 {
-    static_assert(detail::trivialContainer<Container>);
     static_assert(sizeof(*std::data(c)) % sizeof(IntTp) == 0);
     return {reinterpret_cast<IntTp*>(std::data(c)),
             std::size(c) * sizeof(*std::data(c)) / sizeof(IntTp)};