--- /dev/null
+#ifndef __NNCC_CORE_ADT_FEATURE_BUFFER_H__
+#define __NNCC_CORE_ADT_FEATURE_BUFFER_H__
+
+#include "nncc/core/ADT/feature/View.h"
+
+#include <vector>
+
+namespace nncc
+{
+namespace core
+{
+namespace ADT
+{
+namespace feature
+{
+
+template <typename T> class Buffer final : public View<T>
+{
+public:
+ explicit Buffer(const Shape &shape, const Layout &layout) : View<T>{shape, layout}
+ {
+ _buffer.resize(num_elements(shape));
+ }
+
+public:
+ virtual T *base(void) { return _buffer.data(); }
+ virtual const T *base(void) const { return _buffer.data(); }
+
+private:
+ std::vector<T> _buffer;
+};
+
+template <typename T, typename LayoutImpl> Buffer<T> make_buffer(const Shape &shape)
+{
+ return Buffer<T>{shape, LayoutImpl{}};
+}
+
+} // namespace feature
+} // namespace ADT
+} // namespace core
+} // namespace nncc
+
+#endif // __NNCC_CORE_ADT_FEATURE_BUFFER_H__
--- /dev/null
+#ifndef __NNCC_CORE_ADT_FEATURE_OVERLAY_H__
+#define __NNCC_CORE_ADT_FEATURE_OVERLAY_H__
+
+#include "nncc/core/ADT/feature/View.h"
+
+#include <vector>
+
+namespace nncc
+{
+namespace core
+{
+namespace ADT
+{
+namespace feature
+{
+
+template <typename T> class Overlay final : public View<T>
+{
+public:
+ explicit Overlay(const Shape &shape, const Layout &layout, T *base)
+ : View<T>{shape, layout}, _base{base}
+ {
+ // DO NOTHING
+ }
+
+public:
+ virtual T *base(void) { return _base; }
+ virtual const T *base(void) const { return _base; }
+
+private:
+ T *const _base;
+};
+
+template <typename T, typename LayoutImpl> Overlay<T> make_overlay(const Shape &shape, T *base)
+{
+ return Overlay<T>{shape, LayoutImpl{}, base};
+}
+
+} // namespace feature
+} // namespace ADT
+} // namespace core
+} // namespace nncc
+
+#endif // __NNCC_CORE_ADT_FEATURE_OVERLAY_H__
--- /dev/null
+#ifndef __NNCC_CORE_ADT_FEATURE_VIEW_H__
+#define __NNCC_CORE_ADT_FEATURE_VIEW_H__
+
+#include "nncc/core/ADT/feature/Shape.h"
+#include "nncc/core/ADT/feature/Reader.h"
+#include "nncc/core/ADT/feature/Accessor.h"
+#include "nncc/core/ADT/feature/Layout.h"
+
+namespace nncc
+{
+namespace core
+{
+namespace ADT
+{
+namespace feature
+{
+
+template <typename T> class View : public Reader<T>, public Accessor<T>
+{
+public:
+ explicit View(const Shape &shape, const Layout &layout) : _shape{shape}, _layout{layout}
+ {
+ // DO NOTHING
+ }
+
+public:
+ virtual T *base(void) = 0;
+ virtual const T *base(void) const = 0;
+
+public:
+ T at(uint32_t ch, uint32_t row, uint32_t col) const override final
+ {
+ return *(base() + _layout.offset(_shape, ch, row, col));
+ }
+
+public:
+ T &at(uint32_t ch, uint32_t row, uint32_t col) override final
+ {
+ return *(base() + _layout.offset(_shape, ch, row, col));
+ }
+
+public:
+ const Shape &shape(void) const { return _shape; }
+
+private:
+ const Shape _shape;
+ const Layout _layout;
+};
+
+} // namespace feature
+} // namespace ADT
+} // namespace core
+} // namespace nncc
+
+#endif // __NNCC_CORE_ADT_FEATURE_VIEW_H__
--- /dev/null
+#include "nncc/core/ADT/feature/Buffer.h"
+#include "nncc/core/ADT/feature/CHWLayout.h"
+
+#include <gtest/gtest.h>
+
+using nncc::core::ADT::feature::Shape;
+using nncc::core::ADT::feature::CHWLayout;
+using nncc::core::ADT::feature::Buffer;
+
+using nncc::core::ADT::feature::make_buffer;
+
+TEST(ADT_FEATURE_BUFFER, ctor)
+{
+ const Shape shape{4, 6, 3};
+ auto buffer = make_buffer<int, CHWLayout>(shape);
+
+ ASSERT_EQ(buffer.shape().depth(), shape.depth());
+ ASSERT_EQ(buffer.shape().height(), shape.height());
+ ASSERT_EQ(buffer.shape().width(), shape.width());
+}
+
+TEST(ADT_FEATURE_BUFFER, access)
+{
+ const Shape shape{4, 6, 3};
+ auto buffer = make_buffer<int, CHWLayout>(shape);
+
+ ASSERT_EQ(buffer.at(3, 5, 2), 0);
+ buffer.at(3, 5, 2) = 4;
+
+ // Casting is introduced to use 'const T &at(...) const' method
+ ASSERT_EQ(static_cast<const Buffer<int> &>(buffer).at(3, 5, 2), 4);
+}
--- /dev/null
+#include "nncc/core/ADT/feature/Overlay.h"
+#include "nncc/core/ADT/feature/CHWLayout.h"
+
+#include <gtest/gtest.h>
+
+using nncc::core::ADT::feature::Shape;
+using nncc::core::ADT::feature::CHWLayout;
+using nncc::core::ADT::feature::Overlay;
+
+using nncc::core::ADT::feature::make_overlay;
+
+TEST(ADT_FEATURE_OVERLAY, ctor)
+{
+ const Shape shape{4, 6, 3};
+
+ int data[4 * 6 * 3] = {
+ 0,
+ };
+ auto overlay = make_overlay<int, CHWLayout>(shape, data);
+
+ ASSERT_EQ(overlay.shape().depth(), shape.depth());
+ ASSERT_EQ(overlay.shape().height(), shape.height());
+ ASSERT_EQ(overlay.shape().width(), shape.width());
+}
+
+TEST(ADT_FEATURE_OVERLAY, read)
+{
+ const Shape shape{4, 6, 3};
+
+ int data[4 * 6 * 3] = {
+ 0,
+ };
+ const auto overlay = make_overlay<int, CHWLayout>(shape, data);
+
+ CHWLayout layout{};
+
+ ASSERT_EQ(data[layout.offset(shape, 3, 5, 2)], 0);
+ data[layout.offset(shape, 3, 5, 2)] = 2;
+ ASSERT_EQ(overlay.at(3, 5, 2), 2);
+}
+
+TEST(ADT_FEATURE_OVERLAY, access)
+{
+ const Shape shape{4, 6, 3};
+
+ int data[4 * 6 * 3] = {
+ 0,
+ };
+ auto overlay = make_overlay<int, CHWLayout>(shape, data);
+
+ CHWLayout layout{};
+
+ ASSERT_EQ(data[layout.offset(shape, 3, 5, 2)], 0);
+ overlay.at(3, 5, 2) = 4;
+ ASSERT_EQ(data[layout.offset(shape, 3, 5, 2)], 4);
+}