From 552f781f22c87daa80c734329515f7b6601c3cc7 Mon Sep 17 00:00:00 2001 From: Levi Armstrong Date: Sun, 21 Jul 2024 09:00:17 -0500 Subject: [PATCH] Add integral any poly types --- .../include/tesseract_common/any_poly.h | 19 ++++ .../include/tesseract_common/type_erasure.h | 2 +- .../include/tesseract_common/yaml_utils.h | 2 +- tesseract_common/src/any_poly.cpp | 16 +++ .../test/tesseract_common_unit.cpp | 98 +++++++++++++++++++ 5 files changed, 135 insertions(+), 2 deletions(-) diff --git a/tesseract_common/include/tesseract_common/any_poly.h b/tesseract_common/include/tesseract_common/any_poly.h index 4c20ffb47d4..28552240696 100644 --- a/tesseract_common/include/tesseract_common/any_poly.h +++ b/tesseract_common/include/tesseract_common/any_poly.h @@ -35,6 +35,11 @@ TESSERACT_COMMON_IGNORE_WARNINGS_POP #include #include +#include +#include + +#define COMMA , + /** @brief If shared library, this must go in the header after the class definition */ #define TESSERACT_ANY_EXPORT_KEY(C, K) \ namespace tesseract_serialization::any_poly \ @@ -78,6 +83,7 @@ struct AnyConcept // NOLINT A assign = c; bool eq = (c == cp); bool neq = (c != cp); + UNUSED(assign); UNUSED(eq); UNUSED(neq); } @@ -131,4 +137,17 @@ BOOST_CLASS_TRACKING(tesseract_common::AnyPolyBase, boost::serialization::track_ BOOST_CLASS_EXPORT_KEY(tesseract_common::AnyPoly) BOOST_CLASS_TRACKING(tesseract_common::AnyPoly, boost::serialization::track_never) +TESSERACT_ANY_EXPORT_KEY(bool, IntegralBool) +TESSERACT_ANY_EXPORT_KEY(int, IntegralInt) +TESSERACT_ANY_EXPORT_KEY(unsigned, IntegralUnsigned) +TESSERACT_ANY_EXPORT_KEY(double, IntegralDouble) +TESSERACT_ANY_EXPORT_KEY(float, IntegralFloat) +TESSERACT_ANY_EXPORT_KEY(std::string, StdString) +TESSERACT_ANY_EXPORT_KEY(std::unordered_map, StdUnorderedMapStringString) +TESSERACT_ANY_EXPORT_KEY(std::unordered_map, StdUnorderedMapStringBool) +TESSERACT_ANY_EXPORT_KEY(std::unordered_map, StdUnorderedMapStringInt) +TESSERACT_ANY_EXPORT_KEY(std::unordered_map, StdUnorderedMapStringUnsigned) +TESSERACT_ANY_EXPORT_KEY(std::unordered_map, StdUnorderedMapStringDouble) +TESSERACT_ANY_EXPORT_KEY(std::unordered_map, StdUnorderedMapStringFloat) + #endif // TESSERACT_COMMON_ANY_POLY_H diff --git a/tesseract_common/include/tesseract_common/type_erasure.h b/tesseract_common/include/tesseract_common/type_erasure.h index cbdc1ffd6c4..cb5da046d10 100644 --- a/tesseract_common/include/tesseract_common/type_erasure.h +++ b/tesseract_common/include/tesseract_common/type_erasure.h @@ -74,7 +74,7 @@ struct TypeErasureInstance : ConceptInterface using ConceptValueType = ConcreteType; using ConceptInterfaceType = ConceptInterface; - TypeErasureInstance() = default; + TypeErasureInstance() = default; // NOLINT(cppcoreguidelines-pro-type-member-init) explicit TypeErasureInstance(ConcreteType value) : value_(std::move(value)) {} diff --git a/tesseract_common/include/tesseract_common/yaml_utils.h b/tesseract_common/include/tesseract_common/yaml_utils.h index 8bfcbe61610..998cd25f298 100644 --- a/tesseract_common/include/tesseract_common/yaml_utils.h +++ b/tesseract_common/include/tesseract_common/yaml_utils.h @@ -50,7 +50,7 @@ inline void checkForUnknownKeys(const YAML::Node& node, const std::setfirst.as(); + auto key = it->first.as(); if (expected_keys.find(key) == expected_keys.end()) throw std::runtime_error("checkForUnknownKeys, unknown key: " + key); } diff --git a/tesseract_common/src/any_poly.cpp b/tesseract_common/src/any_poly.cpp index f635d392be3..1519701f85b 100644 --- a/tesseract_common/src/any_poly.cpp +++ b/tesseract_common/src/any_poly.cpp @@ -26,6 +26,8 @@ #include +#include + namespace tesseract_common { template @@ -42,3 +44,17 @@ TESSERACT_SERIALIZE_ARCHIVES_INSTANTIATE(tesseract_common::AnyPoly) BOOST_CLASS_EXPORT_IMPLEMENT(tesseract_common::AnyPolyBase) BOOST_CLASS_EXPORT_IMPLEMENT(tesseract_common::AnyPoly) + +TESSERACT_ANY_EXPORT_IMPLEMENT(IntegralBool) +TESSERACT_ANY_EXPORT_IMPLEMENT(IntegralInt) +TESSERACT_ANY_EXPORT_IMPLEMENT(IntegralUnsigned) +TESSERACT_ANY_EXPORT_IMPLEMENT(IntegralDouble) +TESSERACT_ANY_EXPORT_IMPLEMENT(IntegralFloat) +TESSERACT_ANY_EXPORT_IMPLEMENT(StdString) + +TESSERACT_ANY_EXPORT_IMPLEMENT(StdUnorderedMapStringString) +TESSERACT_ANY_EXPORT_IMPLEMENT(StdUnorderedMapStringBool) +TESSERACT_ANY_EXPORT_IMPLEMENT(StdUnorderedMapStringInt) +TESSERACT_ANY_EXPORT_IMPLEMENT(StdUnorderedMapStringUnsigned) +TESSERACT_ANY_EXPORT_IMPLEMENT(StdUnorderedMapStringDouble) +TESSERACT_ANY_EXPORT_IMPLEMENT(StdUnorderedMapStringFloat) diff --git a/tesseract_common/test/tesseract_common_unit.cpp b/tesseract_common/test/tesseract_common_unit.cpp index 2a01b4e9c49..c32b0f307e6 100644 --- a/tesseract_common/test/tesseract_common_unit.cpp +++ b/tesseract_common/test/tesseract_common_unit.cpp @@ -414,6 +414,104 @@ TEST(TesseractCommonUnit, anyUnit) // NOLINT EXPECT_ANY_THROW(nany_type.as()); // NOLINT } +template +void runAnyPolyIntegralTest(T value, const std::string& type_str) +{ + tesseract_common::AnyPoly any_type{ value }; + EXPECT_TRUE(any_type.getType() == std::type_index(typeid(T))); + EXPECT_TRUE(any_type.as() == value); + + // Check clone + tesseract_common::AnyPoly any_copy = any_type; + EXPECT_TRUE(any_copy == any_type); + EXPECT_TRUE(any_copy.as() == value); + + const std::string filepath{ tesseract_common::getTempPath() + "any_" + type_str + "_type_boost.xml" }; + { + std::ofstream os(filepath); + boost::archive::xml_oarchive oa(os); + oa << BOOST_SERIALIZATION_NVP(any_type); + } + + tesseract_common::AnyPoly nany_type; + { + std::ifstream ifs(filepath); + assert(ifs.good()); + boost::archive::xml_iarchive ia(ifs); + + // restore the schedule from the archive + ia >> BOOST_SERIALIZATION_NVP(nany_type); + } + + EXPECT_TRUE(nany_type.getType() == std::type_index(typeid(T))); + EXPECT_TRUE(nany_type.as() == value); + + // Test bad cast + EXPECT_ANY_THROW(nany_type.as()); // NOLINT +} + +TEST(TesseractCommonUnit, anyIntegralTypesUnit) // NOLINT +{ + runAnyPolyIntegralTest(true, "bool"); + runAnyPolyIntegralTest(-10, "int"); + runAnyPolyIntegralTest(5, "unsigned"); + runAnyPolyIntegralTest(1.2, "double"); + runAnyPolyIntegralTest(-0.2F, "float"); + runAnyPolyIntegralTest("this", "string"); +} + +template +void runAnyPolyUnorderedMapIntegralTest(T value, const std::string& type_str) +{ + std::unordered_map data; + data["test"] = value; + tesseract_common::AnyPoly any_type{ data }; + EXPECT_TRUE(any_type.getType() == std::type_index(typeid(std::unordered_map))); + bool check = any_type.as>() == data; + EXPECT_TRUE(check); + + // Check clone + tesseract_common::AnyPoly any_copy = any_type; + EXPECT_TRUE(any_copy == any_type); + check = any_copy.as>() == data; + EXPECT_TRUE(check); + + const std::string filepath{ tesseract_common::getTempPath() + "any_unordered_map_string_" + type_str + + "_type_boost.xml" }; + { + std::ofstream os(filepath); + boost::archive::xml_oarchive oa(os); + oa << BOOST_SERIALIZATION_NVP(any_type); + } + + tesseract_common::AnyPoly nany_type; + { + std::ifstream ifs(filepath); + assert(ifs.good()); + boost::archive::xml_iarchive ia(ifs); + + // restore the schedule from the archive + ia >> BOOST_SERIALIZATION_NVP(nany_type); + } + + EXPECT_TRUE(nany_type.getType() == std::type_index(typeid(std::unordered_map))); + check = nany_type.as>() == data; + EXPECT_TRUE(check); + + // Test bad cast + EXPECT_ANY_THROW(nany_type.as()); // NOLINT +} + +TEST(TesseractCommonUnit, anyUnorderedMapIntegralTypesUnit) // NOLINT +{ + runAnyPolyUnorderedMapIntegralTest(true, "bool"); + runAnyPolyUnorderedMapIntegralTest(-10, "int"); + runAnyPolyUnorderedMapIntegralTest(5, "unsigned"); + runAnyPolyUnorderedMapIntegralTest(1.2, "double"); + runAnyPolyUnorderedMapIntegralTest(-0.2F, "float"); + runAnyPolyUnorderedMapIntegralTest("this", "string"); +} + TEST(TesseractCommonUnit, anySharedPtrUnit) // NOLINT { tesseract_common::AnyPoly any_type;