--- /dev/null
+#ifndef __NNCC_CORE_ADT_TENSOR_VIEW_H__
+#define __NNCC_CORE_ADT_TENSOR_VIEW_H__
+
+#include "nncc/core/ADT/tensor/Shape.h"
+#include "nncc/core/ADT/tensor/Index.h"
+#include "nncc/core/ADT/tensor/Reader.h"
+#include "nncc/core/ADT/tensor/Accessor.h"
+#include "nncc/core/ADT/tensor/Layout.h"
+
+#include <nncc/foundation/Region.h>
+
+#include <memory>
+
+namespace nncc
+{
+namespace core
+{
+namespace ADT
+{
+namespace tensor
+{
+
+template <typename T> class View final : public Reader<T>, public Accessor<T>
+{
+public:
+ explicit View(const Shape &shape, std::unique_ptr<Layout> &&layout,
+ std::unique_ptr<nncc::foundation::Region<T>> &®ion)
+ : _shape{shape}, _layout{std::move(layout)}, _region{std::move(region)}
+ {
+ // DO NOTHING
+ }
+
+public:
+ T at(const Index &index) const override
+ {
+ return *(_region->base() + _layout->offset(_shape, index));
+ }
+
+public:
+ T &at(const Index &index) override { return *(_region->base() + _layout->offset(_shape, index)); }
+
+public:
+ const Shape &shape(void) const { return _shape; }
+
+private:
+ const Shape _shape;
+ std::unique_ptr<Layout> _layout;
+
+private:
+ std::unique_ptr<nncc::foundation::Region<T>> _region;
+};
+
+template <typename T, typename LayoutImpl>
+View<T> make_view(const Shape &shape, std::unique_ptr<nncc::foundation::Region<T>> &®ion)
+{
+ std::unique_ptr<Layout> layout(new LayoutImpl{});
+ return View<T>{shape, std::move(layout), std::move(region)};
+}
+
+} // namespace tensor
+} // namespace ADT
+} // namespace core
+} // namespace nncc
+
+#endif // __NNCC_CORE_ADT_TENSOR_VIEW_H__
--- /dev/null
+#include "nncc/core/ADT/tensor/View.h"
+#include "nncc/core/ADT/tensor/LexicalLayout.h"
+
+#include <nncc/foundation/Memory.h>
+#include <nncc/foundation/ExternalRegion.h>
+
+#include <gtest/gtest.h>
+
+using namespace nncc::core::ADT::tensor;
+
+using nncc::foundation::make_unique;
+using nncc::foundation::ExternalRegion;
+
+TEST(ADT_TENSOR_VIEW, ctor)
+{
+ const Shape shape{2, 3};
+
+ int data[2 * 3] = {
+ 0,
+ };
+ auto region = make_unique<ExternalRegion<int>>(data, 2 * 3);
+ auto view = make_view<int, LexicalLayout>(shape, std::move(region));
+
+ ASSERT_EQ(view.shape(), shape);
+}
+
+TEST(ADT_TENSOR_VIEW, read)
+{
+ const Shape shape{2, 3};
+
+ int data[2 * 3] = {
+ 0,
+ };
+ auto region = make_unique<ExternalRegion<int>>(data, 2 * 3);
+ const auto view = make_view<int, LexicalLayout>(shape, std::move(region));
+
+ LexicalLayout layout{};
+
+ const Index index{1, 2};
+
+ ASSERT_EQ(data[layout.offset(shape, index)], 0);
+ data[layout.offset(shape, index)] = 2;
+ ASSERT_EQ(view.at(index), 2);
+}
+
+TEST(ADT_TENSOR_VIEW, access)
+{
+ const Shape shape{2, 3};
+
+ int data[2 * 3] = {
+ 0,
+ };
+ auto region = make_unique<ExternalRegion<int>>(data, 2 * 3);
+ auto view = make_view<int, LexicalLayout>(shape, std::move(region));
+
+ LexicalLayout layout{};
+
+ const Index index{1, 2};
+
+ ASSERT_EQ(data[layout.offset(shape, index)], 0);
+ view.at(index) = 4;
+ ASSERT_EQ(data[layout.offset(shape, index)], 4);
+}