Property: provide a fallback serialize() implementation

... in case operator<< is not defined for type T
This commit is contained in:
Robert Haschke 2018-04-28 21:53:04 +02:00
parent cf84f261a0
commit 2106c51c9d
2 changed files with 20 additions and 3 deletions

View File

@ -49,6 +49,14 @@
namespace moveit {
namespace task_constructor {
// hasSerialize<T>::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 <typename T, typename = std::ostream&>
struct hasSerialize : std::false_type {};
template <typename T>
struct hasSerialize<T, decltype(std::declval<std::ostringstream&>() << std::declval<T>())> : std::true_type {};
class Property;
class PropertyMap;
@ -74,13 +82,18 @@ class Property {
const Property::SerializeFunction &serialize);
template <typename T>
static std::string serialize(const boost::any& value) {
static typename std::enable_if<hasSerialize<T>::value, std::string>::type serialize(const boost::any& value) {
if (value.empty()) return "";
std::ostringstream oss;
oss << boost::any_cast<T>(value);
return oss.str();
}
template <typename T>
static typename std::enable_if<!hasSerialize<T>::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;

View File

@ -80,9 +80,13 @@ TEST(Property, reset) {
TEST(Property, serialize) {
PropertyMap props;
props.declare<int>("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<std::map<int, int>>("map", std::map<int, int>());
EXPECT_THROW(props.property("map").serialize(), std::runtime_error);
}
class InitFromTest : public ::testing::Test {