--- /dev/null
+#ifndef __COCO_IR_DEP_H__
+#define __COCO_IR_DEP_H__
+
+#include "coco/IR/Bag.h"
+#include "coco/IR/BagInfo.forward.h"
+#include "coco/IR/Object.forward.h"
+
+#include "coco/ADT/PtrLink.h"
+
+namespace coco
+{
+
+/**
+ * @brief A Dep represents the edge between a Bag and its dependent Object
+ *
+ * WARNING A Dep will update dependent Object set (stored BagInfo) only when
+ * users properly initialize object and link values.
+ */
+class Dep final
+{
+public:
+ Dep() = default;
+
+public:
+ Dep(const Dep &) = delete;
+ Dep(Dep &&) = delete;
+
+public:
+ ~Dep();
+
+public:
+ Bag *bag(void) const { return _bag; }
+ void bag(Bag *);
+
+public:
+ Object *object(void) const { return _object; }
+ void object(Object *object) { _object = object; }
+
+public:
+ void link(const PtrLink<Bag, BagInfo> *link) { _link = link; }
+
+private:
+ Bag *_bag = nullptr;
+ Object *_object = nullptr;
+
+private:
+ const PtrLink<Bag, BagInfo> *_link = nullptr;
+};
+
+} // namespace coco
+
+#endif // __COCO_IR_DEP_H__
--- /dev/null
+#include "coco/IR/Dep.h"
+#include "coco/IR/BagInfo.h"
+#include "coco/IR/Object.h"
+
+#include <cassert>
+
+namespace coco
+{
+
+Dep::~Dep() { bag(nullptr); }
+
+void Dep::bag(Bag *bag)
+{
+ if (_bag != nullptr)
+ {
+ // Remove bag <-> object link (if possible)
+ if (_link && _object)
+ {
+ auto info = _link->find(_bag);
+ assert(info != nullptr);
+ assert(info->object()->find(_object) != info->object()->end());
+
+ info->object()->erase(_object);
+ }
+
+ // Reset _bag
+ _bag = nullptr;
+ }
+
+ assert(_bag == nullptr);
+
+ if (bag != nullptr)
+ {
+ // Set _bag
+ _bag = bag;
+
+ // Create bag <-> object link (if possible)
+ if (_link && _object)
+ {
+ auto info = _link->find(bag);
+ assert(info != nullptr);
+ info->object()->insert(_object);
+ }
+ }
+
+ assert(_bag == bag);
+}
+
+} // namespace coco
--- /dev/null
+#include "coco/IR/Dep.h"
+
+#include "coco/IR/BagInfo.h"
+#include "coco/IR/BagManager.h"
+
+#include "coco/IR/ObjectInfo.h"
+#include "coco/IR/ObjectManager.h"
+#include "coco/IR/FeatureObject.h"
+
+#include <gtest/gtest.h>
+
+using namespace nncc::core::ADT;
+
+namespace
+{
+class DepTest : public ::testing::Test
+{
+protected:
+ coco::PtrLink<coco::Bag, coco::BagInfo> bag_link;
+ coco::PtrLink<coco::Object, coco::ObjectInfo> obj_link;
+
+ coco::BagManager bag_mgr{&bag_link};
+ coco::ObjectManager obj_mgr{&obj_link, &bag_link};
+};
+} // namespace
+
+TEST_F(DepTest, default_constructor)
+{
+ coco::Dep dep;
+
+ ASSERT_EQ(dep.bag(), nullptr);
+ ASSERT_EQ(dep.object(), nullptr);
+}
+
+TEST_F(DepTest, bag_update)
+{
+ auto bag = bag_mgr.create(3);
+
+ coco::Dep dep;
+
+ // NOTE b->object() is not updated here
+ dep.bag(bag);
+
+ ASSERT_EQ(dep.bag(), bag);
+}
+
+TEST_F(DepTest, bag_update_with_link_and_object)
+{
+ auto bag = bag_mgr.create(3);
+ auto obj = obj_mgr.create(feature::Shape{1, 1, 3});
+
+ coco::Dep dep;
+
+ dep.link(&bag_link);
+ dep.object(obj);
+
+ dep.bag(bag);
+
+ auto deps = *(bag->object());
+
+ ASSERT_EQ(deps.size(), 1);
+ ASSERT_NE(deps.count(obj), 0);
+}