Class array_ref

Synopsis

#include <include/type_safe/reference.hpp>

template <typename T, bool XValue = false>
class array_ref

Description

A reference to an array of objects of type T.

It is a simple pointer + size pair that allows reference access to each element in the array. An "array" here is any contiguous storage (so C arrays, [std::vector](), etc.). It does not allow changing the size of the array, only the individual elements. Like [ts::object_ref]() it can be safely used in containers.

If the given type is const, it will only return a const reference to each element, but then XValue must be false.

If XValue is true, dereferencing will [std::move()]() the object, modelling a reference to an expiring lvalue. \notes T is the type stored in the array, so array_ref<int> to reference a contiguous storage of ints. \notes Unlike the other types it isn't technically non-null, as it may contain an empty array. But the range [data(), data() + size) will always be valid.

Mentioned in

Methods

array_ref overload\effects Sets the reference to an empty array
array_ref overload\effects Sets the reference to the memory range [begin, end)
array_ref overload\effects Sets the reference to the memory range [array, array + size)
array_ref overload\effects Sets the reference to the C array
assign overload\group empty
assign overload\group range
assign overload\group ptr_size
assign overload\group c_array
beginReturns: An iterator to the beginning of the array.
dataReturns: A pointer to the beginning of the array
endReturns: An iterator one past the last element of the array.
operator[]Returns: A (rvalue if Xvalue is true) reference to the ith element of the array
sizeReturns: The number of elements in the array.

Source

Lines 286-393 in include/type_safe/reference.hpp.

template <typename T, bool XValue = false>
class array_ref
{
    static_assert(!std::is_void<T>::value, "must not be void");
    static_assert(!std::is_reference<T>::value, "pass the type without reference");
    static_assert(!XValue || !std::is_const<T>::value, "must not be const if xvalue reference");

public:
    using value_type     = T;
    using reference_type = typename std::conditional<XValue, T&&, T&>::type;
    using iterator       = T*;

    /// \effects Sets the reference to an empty array.
    /// \group empty
    array_ref(std::nullptr_t) : begin_(nullptr), size_(0u) {}

    /// \effects Sets the reference to the memory range `[begin, end)`.
    /// \requires `begin <= end`.
    /// \group range
    array_ref(T* begin, T* end) noexcept : size_(0u)
    {
        assign(begin, end);
    }

    /// \effects Sets the reference to the memory range `[array, array + size)`.
    /// \requires `array` must not be `nullptr` unless `size` is `0`.
    /// \group ptr_size
    array_ref(T* array, size_t size) noexcept : size_(size)
    {
        assign(array, size);
    }

    /// \effects Sets the reference to the C array.
    /// \group c_array
    template <std::size_t Size>
    explicit array_ref(T (&arr)[Size]) : begin_(arr), size_(Size)
    {}

    /// \group empty
    void assign(std::nullptr_t) noexcept
    {
        begin_ = nullptr;
        size_  = 0u;
    }

    /// \group range
    void assign(T* begin, T* end) noexcept
    {
        DEBUG_ASSERT(begin <= end, detail::precondition_error_handler{}, "invalid array bounds");
        begin_ = begin;
        size_  = static_cast<size_t>(make_unsigned(end - begin));
    }

    /// \group ptr_size
    void assign(T* array, size_t size) noexcept
    {
        DEBUG_ASSERT(size == 0u || array, detail::precondition_error_handler{},
                     "invalid array bounds");
        begin_ = array;
        size_  = size;
    }

    /// \group c_array
    template <std::size_t Size>
    void assign(T (&arr)[Size]) noexcept
    {
        begin_ = arr;
        size_  = Size;
    }

    /// \returns An iterator to the beginning of the array.
    iterator begin() const noexcept
    {
        return begin_;
    }

    /// \returns An iterator one past the last element of the array.
    iterator end() const noexcept
    {
        return begin_ + static_cast<std::size_t>(size_);
    }

    /// \returns A pointer to the beginning of the array.
    /// If `size()` isn't zero, the pointer is guaranteed to be non-null.
    T* data() const noexcept
    {
        return begin_;
    }

    /// \returns The number of elements in the array.
    size_t size() const noexcept
    {
        return size_;
    }

    /// \returns A (`rvalue` if `Xvalue` is `true`) reference to the `i`th element of the array.
    /// \requires `i < size()`.
    reference_type operator[](index_t i) const noexcept
    {
        DEBUG_ASSERT(static_cast<size_t&>(i) < size_, detail::precondition_error_handler{},
                     "out of bounds array access");
        return static_cast<reference_type>(at(begin_, i));
    }

private:
    T*     begin_;
    size_t size_;
};





Add Discussion as Guest

Log in