--- /dev/null
+add_subdirectory(core)
--- /dev/null
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(coco_core STATIC ${SOURCES})
+set_target_properties(coco_core PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_include_directories(coco_core PUBLIC include)
+
+nncc_find_package(GTest QUIET)
+
+if(NOT GTest_FOUND)
+ return()
+endif(NOT GTest_FOUND)
+
+add_executable(coco_core_test ${TESTS})
+target_link_libraries(coco_core_test gtest_main)
+target_link_libraries(coco_core_test coco_core)
+add_test(coco_core_test coco_core_test)
--- /dev/null
+#ifndef __COCO_ADT_PTR_LIST_H__
+#define __COCO_ADT_PTR_LIST_H__
+
+#include <vector>
+
+#include <cstdint>
+
+namespace coco
+{
+
+template<typename T> class PtrList
+{
+public:
+ PtrList() = default;
+
+public:
+ PtrList(const PtrList &) = delete;
+ PtrList(PtrList &&) = delete;
+
+public:
+ virtual ~PtrList() = default;
+
+public:
+ uint32_t size(void) const { return _ptrs.size(); }
+
+public:
+ T *at(uint32_t n) const { return _ptrs.at(n); }
+
+public:
+ void insert(T *ptr) { _ptrs.emplace_back(ptr); }
+
+private:
+ std::vector<T *> _ptrs;
+};
+
+} // namespace coco
+
+#endif // __COCO_ADT_PTR_LIST_H__
--- /dev/null
+#include "coco/ADT/PtrList.h"
+
+// NOTE Do NOT delete this file; this file checks the completeness of 'PtrList.h'
--- /dev/null
+#include "coco/ADT/PtrList.h"
+
+#include <memory>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+struct Object { };
+}
+
+TEST(ADT_PTR_LIST, ctor)
+{
+ coco::PtrList<Object> l;
+
+ ASSERT_EQ(l.size(), 0);
+}
+
+TEST(ADT_PTR_LIST, insert)
+{
+ coco::PtrList<Object> l;
+
+ std::unique_ptr<Object> ptr{new Object};
+
+ l.insert(ptr.get());
+
+ ASSERT_EQ(l.size(), 1);
+ ASSERT_EQ(l.at(0), ptr.get());
+}