diff --git a/core/include/moveit/task_constructor/properties.h b/core/include/moveit/task_constructor/properties.h index f0c0282a..e2496c0b 100644 --- a/core/include/moveit/task_constructor/properties.h +++ b/core/include/moveit/task_constructor/properties.h @@ -49,6 +49,14 @@ namespace moveit { namespace task_constructor { +// hasSerialize::value provides a true/false constexpr depending on whether operator<< is supported. +// This uses SFINAE, extracted from https://jguegant.github.io/blogs/tech/sfinae-introduction.html +template +struct hasSerialize : std::false_type {}; + +template +struct hasSerialize() << std::declval())> : std::true_type {}; + class Property; class PropertyMap; @@ -74,13 +82,18 @@ class Property { const Property::SerializeFunction &serialize); template - static std::string serialize(const boost::any& value) { + static typename std::enable_if::value, std::string>::type serialize(const boost::any& value) { if (value.empty()) return ""; std::ostringstream oss; oss << boost::any_cast(value); return oss.str(); } + template + static typename std::enable_if::value, std::string>::type serialize(const boost::any& value) { + throw std::runtime_error (std::string("no operator<< for type ") + typeid(T).name()); + } + public: /// base class for Property exceptions class error; diff --git a/core/test/test_properties.cpp b/core/test/test_properties.cpp index 5a5bd740..9b1ed1ee 100644 --- a/core/test/test_properties.cpp +++ b/core/test/test_properties.cpp @@ -80,9 +80,13 @@ TEST(Property, reset) { TEST(Property, serialize) { PropertyMap props; props.declare("int"); - EXPECT_STREQ(props.property("int").serialize().c_str(), ""); + EXPECT_EQ(props.property("int").serialize(), ""); props.set("int", 42); - EXPECT_STREQ(props.property("int").serialize().c_str(), "42"); + EXPECT_EQ(props.property("int").serialize(), "42"); + + // std::map doesn't provide operator<< serialization + props.declare>("map", std::map()); + EXPECT_THROW(props.property("map").serialize(), std::runtime_error); } class InitFromTest : public ::testing::Test {