template <typename T>
struct is_const_impl { static constexpr bool value = false; };
template <typename T>
struct is_const_impl<const T> { static constexpr bool value = true; };
template <typename T>
concept is_const = is_const_impl<T>::value;
template <typename T>
concept is_mut = !is_const<T>;
struct empty {};
template <bool condition, typename T, typename F>
struct type_if_impl { using type = F; };
template <typename T, typename F>
struct type_if_impl<true, T, F> { using type = T; };
template <bool condition, typename T, typename F>
using type_if = typename type_if_impl<condition, T, F>::type;
template <typename T, i64 N = -1>
class slice
{
public:
constexpr
slice(T* const ptr, i64 const len) noexcept
requires (N == -1)
: ptr_{ptr}
, len_{len}
{}
constexpr
slice(T* const ptr) noexcept
requires (N >= 0)
: ptr_{ptr}
{}
template <u32 L>
constexpr
slice(T (&raw)[L]) noexcept
requires (N == L)
: slice{raw}
{}
constexpr
T const*
as_ptr() const noexcept
{
return ptr_;
}
constexpr
T* as_mut_ptr() const noexcept
requires is_mut<T>
{
return ptr_;
}
constexpr
i64
len() const noexcept
{
if constexpr (N == -1)
{
return len_;
}
else
{
return N;
}
}
constexpr
operator slice<T, -1>() const noexcept
requires (N >= 0)
{
return slice<T, -1>{ptr_, N};
}
private:
T* ptr_;
[[no_unique_address]]
type_if<N == -1, i64, empty> len_;
};
template<typename T, u32 N>
slice(T (&)[N]) -> slice<T, N>;
I'd like to see cnile version of this.