Multidimensional Arrays and std::mdspan

Accessor Policy in mdspan

What is the purpose of the accessor policy in mdspan?

Abstract art representing computer programming

The accessor policy in std::mdspan is an optional template parameter that allows you to customize how elements are accessed and potentially modified when using the [] operator or the accessor member function of mdspan.

The primary purposes of the accessor policy are:

Customizing Element Access Behavior

The accessor policy enables you to define custom behavior for accessing elements in the mdspan. This can be useful in various scenarios, such as:

  • Adding bounds checking: You can implement an accessor policy that checks if the accessed indices are within the valid range of the mdspan, preventing out-of-bounds access.
  • Applying transformations: You can define an accessor policy that applies certain transformations to the elements before returning them, such as scaling, offsetting, or type conversions.
  • Implementing read-only or write-only access: You can create accessor policies that restrict access to read-only or write-only operations, enforcing specific access patterns.

Interoperability with External Libraries or APIs

When working with external libraries or APIs that expect a specific accessor behavior, you can use an appropriate accessor policy to adapt the mdspan to match those expectations.

For example, if an external library expects accessor objects with certain member functions or operators, you can define an accessor policy that provides those required interfaces.

Performance Optimization

In some cases, the accessor policy can be used to optimize element access performance. By defining a custom accessor policy, you can avoid unnecessary function calls or indirections and provide a more efficient way to access elements.

However, it's important to note that the performance impact of accessor policies depends on the specific use case and compiler optimizations. In many cases, the default accessor policy provided by std::mdspan is already optimized for common scenarios.

Here's an example that demonstrates a custom accessor policy that applies a scaling factor to the elements:

#include <iostream>
#include <mdspan>

// Custom accessor policy that scales
// elements by a factor of 10
struct ScalingAccessor {
  template <typename T>
  struct accessor {
    T* data;

    accessor(T* ptr) : data(ptr) {}

    T read(std::size_t offset) const {
      return data[offset] * 10;  
    }

    void write(std::size_t offset, T value) {
      data[offset] = value / 10;  
    }
  };
};

int main() {
  std::array<int, 6> arr{1, 2, 3, 4, 5, 6};
  std::mdspan<int, std::extents<
    std::size_t, 2, 3>, std::layout_right,
      ScalingAccessor>
      scalingSpan{arr.data()};

  std::cout << "Original elements:\n";
  for (std::size_t i = 0;
    i < scalingSpan.extent(0); ++i) {
    for (std::size_t j = 0;
      j < scalingSpan.extent(1); ++j) {
      std::cout << scalingSpan[i, j] << " ";
    }
    std::cout << "\n";
  }

  // Modify elements through the accessor policy
  scalingSpan[0, 0] = 10;
  scalingSpan[1, 1] = 50;

  std::cout << "\nModified elements:\n";
  for (std::size_t i = 0;
    i < scalingSpan.extent(0); ++i) {
    for (std::size_t j = 0;
      j < scalingSpan.extent(1); ++j) {
      std::cout
        << arr[i * scalingSpan.extent(1) + j]
        << " ";
    }
    std::cout << "\n";
  }
}
Original elements:
10 20 30
40 50 60

Modified elements:
1 2 3
4 5 6

In this example, we define a custom accessor policy called ScalingAccessor that scales the elements by a factor of 10 when reading and divides them by 10 when writing.

We create an mdspan object scalingSpan with the ScalingAccessor policy. When accessing elements through scalingSpan, the scaling behavior is applied transparently.

Note that the accessor policy only affects the access through the mdspan object. When we modify elements through scalingSpan, the underlying array arr is updated with the original unscaled values.

Accessor policies provide a powerful way to customize element access behavior in mdspan, enabling various use cases and optimizations.

Answers to questions are automatically generated and may not have been reviewed.

Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved