UseSet _uses;
};
+/**
+ * @brief Check whether a given object is of type T
+ *
+ * The example below shows how to use this "isa<T>" helper:
+ * auto obj = new FeatureObject{};
+ *
+ * if (isa<FeatureObject>())
+ * {
+ * std::cout << "FeatureObject" << std::endl;
+ * }
+ */
+template <typename T> bool isa(const Object *);
+
+/**
+ * @brief Cast a generic object as a specific one
+ *
+ * "cast<T>(o)" accepts only a valid object pointer "o" that "isa<T>(o)" holds
+ * - Then, "cast<T>(o)" always returns a valid object pointer.
+ */
+template <typename T> T *cast(Object *);
+
+/**
+ * @brief Cast a generic object as a specific one
+ *
+ * Unlike "cast<T>", "safe_cast<T>" accepts any object pointer
+ * - "safe_cast<T>(nullptr)" returns "nullptr"
+ * - "safe_cast<T>(o)" returns "nullptr" if "isa<T>(o)" does not hold
+ */
+template <typename T> T *safe_cast(Object *);
+
// @brief Return the producer of a given object if it exists
Object::Producer *producer(const Object *);
class FeatureObjectTest : public ::testing::Test
{
protected:
+ coco::FeatureObject *allocate()
+ {
+ auto o = new coco::FeatureObject{};
+ _allocated.emplace_back(o);
+ return o;
+ }
+
// TODO Deprecate this method
coco::FeatureObject *allocate(const coco::FeatureShape &shape)
{
ASSERT_NE(mutable_object->asFeature(), nullptr);
ASSERT_EQ(mutable_object->asFeature(), immutable_object->asFeature());
}
+
+TEST_F(FeatureObjectTest, casting_helpers)
+{
+ auto obj = allocate();
+
+ ASSERT_TRUE(coco::isa<coco::FeatureObject>(obj));
+ ASSERT_EQ(coco::cast<coco::FeatureObject>(obj), obj);
+ ASSERT_EQ(coco::safe_cast<coco::FeatureObject>(obj), obj);
+}
class KernelObjectTest : public ::testing::Test
{
protected:
+ coco::KernelObject *allocate()
+ {
+ auto o = new coco::KernelObject{};
+ _allocated.emplace_back(o);
+ return o;
+ }
+
coco::KernelObject *allocate(const kernel::Shape &shape)
{
auto o = new coco::KernelObject{shape};
ASSERT_EQ(mutable_object->asKernel(), immutable_object->asKernel());
}
+TEST_F(KernelObjectTest, casting_helpers)
+{
+ auto obj = allocate();
+
+ ASSERT_TRUE(coco::isa<coco::KernelObject>(obj));
+ ASSERT_EQ(coco::cast<coco::KernelObject>(obj), obj);
+ ASSERT_EQ(coco::safe_cast<coco::KernelObject>(obj), obj);
+}
+
// TODO Rewrite this test as a test for GenericKernelLayout
#if 0
TEST_F(KernelObjectTest, at)
return res;
}
+
+/**
+ * Casting Helpers
+ *
+ * TODO Use Macro to reduce code duplication
+ */
+template <> bool isa<FeatureObject>(const Object *o) { return o->asFeature() != nullptr; }
+template <> bool isa<KernelObject>(const Object *o) { return o->asKernel() != nullptr; }
+
+template <> FeatureObject *cast(Object *o)
+{
+ assert(o != nullptr);
+ auto res = o->asFeature();
+ assert(res != nullptr);
+ return res;
+}
+
+template <> KernelObject *cast(Object *o)
+{
+ assert(o != nullptr);
+ auto res = o->asKernel();
+ assert(res != nullptr);
+ return res;
+}
+
+template <> FeatureObject *safe_cast(Object *o)
+{
+ // NOTE o may be nullptr
+ return (o == nullptr) ? nullptr : o->asFeature();
+}
+
+template <> KernelObject *safe_cast(Object *o)
+{
+ // NOTE o may be nullptr
+ return (o == nullptr) ? nullptr : o->asKernel();
+}
+
} // namespace coco
ASSERT_EQ(deps.size(), 0);
}
}
+
+TEST_F(ObjectTest, safe_cast)
+{
+ ASSERT_EQ(coco::safe_cast<coco::FeatureObject>(nullptr), nullptr);
+ ASSERT_EQ(coco::safe_cast<coco::KernelObject>(nullptr), nullptr);
+}