//********************************************************
// The following code example is taken from the book
//  C++23 - The Complete Guide
//  by Nicolai M. Josuttis (www.josuttis.com)
//  http://www.cppstd23.com
//
// The code is licensed under a
//  Creative Commons Attribution 4.0 International License
//  http://creativecommons.org/licenses/by/4.0/
//********************************************************


#include <mdspan>
#include <type_traits>

template<typename ElemT>
struct DefAccessor
{
  static_assert(!std::is_array_v<ElemT>,
               "Accesssor element type must not be an array type");
  static_assert(!std::is_abstract_v<ElemT>,
                "Accesssor element type must not be an abstract class type");

  using offset_policy = DefAccessor;
  using element_type = ElemT;
  using reference = element_type&;
  using data_handle_type = element_type*;

  constexpr DefAccessor() noexcept = default;

  template<typename OtherElemT>
  requires std::is_convertible_v<OtherElemT(*)[], element_type(*)[]>
  constexpr DefAccessor(DefAccessor<OtherElemT>) noexcept { 
  }

  constexpr reference access(data_handle_type p, size_t i) const noexcept {
    return p[i]; 
  }

  constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept {
    return p + i; 
  }
};

