--- /dev/null
+#ifndef __COCO_IR_DEF_SLOT_H__
+#define __COCO_IR_DEF_SLOT_H__
+
+#include "coco/IR/DefHook.h"
+
+namespace coco
+{
+
+template <typename T> class DefSlot final
+{
+public:
+ DefSlot(const PtrLink<Object, ObjectInfo> *obj_link, Object::Def *use)
+ : _hook{obj_link, use}, _value{nullptr}
+ {
+ }
+
+public:
+ T *value(void) const { return _value; }
+
+public:
+ void value(T *value)
+ {
+ if (_value)
+ {
+ _hook.onRelease(_value);
+ _value = nullptr;
+ }
+
+ assert(_value == nullptr);
+
+ if (value)
+ {
+ _value = value;
+ _hook.onTake(_value);
+ }
+
+ assert(_value == value);
+ }
+
+private:
+ DefHook _hook;
+ T *_value;
+};
+
+} // namespace coco
+
+#endif // __COCO_IR_DEF_SLOT_H__
--- /dev/null
+#include "coco/IR/DefSlot.h"
+#include "coco/IR/ObjectInfo.h"
+#include "coco/IR/ObjectManager.h"
+
+#include "coco/IR/FeatureObject.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+namespace mock
+{
+struct Def final : public coco::Object::Def
+{
+};
+} // namespace mock
+} // namespace
+
+namespace
+{
+class DefSlotTest : public ::testing::Test
+{
+protected:
+ coco::PtrLink<coco::Bag, coco::BagInfo> bag_link;
+ coco::PtrLink<coco::Object, coco::ObjectInfo> obj_link;
+
+ coco::ObjectManager obj_mgr{&obj_link, &bag_link};
+};
+} // namespace
+
+TEST_F(DefSlotTest, constructor)
+{
+ auto o = obj_mgr.create(nncc::core::ADT::feature::Shape{1, 1, 1});
+
+ ::mock::Def def;
+
+ coco::DefSlot<coco::FeatureObject> slot{&obj_link, &def};
+
+ ASSERT_EQ(slot.value(), nullptr);
+}
+
+TEST_F(DefSlotTest, value)
+{
+ auto o = obj_mgr.create(nncc::core::ADT::feature::Shape{1, 1, 1});
+
+ ::mock::Def def;
+
+ coco::DefSlot<coco::FeatureObject> slot{&obj_link, &def};
+
+ slot.value(o);
+
+ ASSERT_EQ(slot.value(), o);
+
+ ASSERT_EQ(o->def(), &def);
+
+ slot.value(nullptr);
+
+ ASSERT_EQ(o->def(), nullptr);
+}