raw: Simplify handling of const references

Change-Id: I0cf6ad09160e6c058437fe628e5ab7cab090d579
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/stdplus/raw.hpp b/src/stdplus/raw.hpp
index 2d8f8ee..638a813 100644
--- a/src/stdplus/raw.hpp
+++ b/src/stdplus/raw.hpp
@@ -13,12 +13,23 @@
 namespace detail
 {
 
+/** @brief Gets the datatype referenced in a container
+ */
+template <typename Container>
+using dataType = std::remove_pointer_t<decltype(
+    std::data(std::declval<std::add_lvalue_reference_t<Container>>()))>;
+
 /** @brief Determines if the container holds trivially copyable data
  */
 template <typename Container>
 inline constexpr bool trivialContainer =
-    std::is_trivially_copyable_v<std::remove_pointer_t<decltype(
-        std::data(std::declval<std::add_lvalue_reference_t<Container>>()))>>;
+    std::is_trivially_copyable_v<dataType<Container>>;
+
+/** @brief Adds const to A if B is const
+ */
+template <typename A, typename B>
+using copyConst =
+    std::conditional_t<std::is_const_v<B>, std::add_const_t<A>, A>;
 
 } // namespace detail
 
@@ -110,41 +121,24 @@
 #ifdef STDPLUS_SPAN_TYPE
 template <typename IntT, typename T,
           typename = std::enable_if_t<std::is_integral_v<IntT>>,
-          typename = std::enable_if_t<std::is_trivially_copyable_v<T>>>
-span<IntT> asSpan(T& t) noexcept
+          typename = std::enable_if_t<std::is_trivially_copyable_v<T>>,
+          typename IntTp = detail::copyConst<IntT, T>>
+span<IntTp> asSpan(T& t) noexcept
 {
-    static_assert(sizeof(T) % sizeof(IntT) == 0);
-    return {reinterpret_cast<IntT*>(&t), sizeof(T) / sizeof(IntT)};
+    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_integral_v<IntT>>,
           typename = std::enable_if_t<!std::is_trivially_copyable_v<Container>>,
-          typename = decltype(std::data(std::declval<Container>()))>
-span<IntT> asSpan(Container& c) noexcept
+          typename = decltype(std::data(std::declval<Container>())),
+          typename IntTp = detail::copyConst<IntT, detail::dataType<Container>>>
+span<IntTp> asSpan(Container& c) noexcept
 {
     static_assert(detail::trivialContainer<Container>);
-    static_assert(sizeof(*std::data(c)) % sizeof(IntT) == 0);
-    return {reinterpret_cast<IntT*>(std::data(c)),
-            std::size(c) * sizeof(*std::data(c)) / sizeof(IntT)};
-}
-template <typename IntT, typename T,
-          typename = std::enable_if_t<std::is_integral_v<IntT>>,
-          typename = std::enable_if_t<std::is_trivially_copyable_v<T>>>
-span<const IntT> asSpan(const T& t) noexcept
-{
-    static_assert(sizeof(T) % sizeof(IntT) == 0);
-    return {reinterpret_cast<const IntT*>(&t), sizeof(T) / sizeof(IntT)};
-}
-template <typename IntT, typename Container,
-          typename = std::enable_if_t<std::is_integral_v<IntT>>,
-          typename = std::enable_if_t<!std::is_trivially_copyable_v<Container>>,
-          typename = decltype(std::data(std::declval<Container>()))>
-span<const IntT> asSpan(const Container& c) noexcept
-{
-    static_assert(detail::trivialContainer<Container>);
-    static_assert(sizeof(*std::data(c)) % sizeof(IntT) == 0);
-    return {reinterpret_cast<const IntT*>(std::data(c)),
-            std::size(c) * sizeof(*std::data(c)) / sizeof(IntT)};
+    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)};
 }
 #endif