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