From e5bd0b136f8721b47d1852703d6640791ee0424f Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Tue, 23 Jan 2018 11:24:28 -0500 Subject: [PATCH] Allow AnyValue to convert implicitly from long int to double --- include/cantera/base/AnyMap.h | 15 +++++++ src/base/AnyMap.cpp | 68 +++++++++++++++++++++++++++++++- test/general/test_containers.cpp | 13 ++++++ 3 files changed, 95 insertions(+), 1 deletion(-) diff --git a/include/cantera/base/AnyMap.h b/include/cantera/base/AnyMap.h index c31365889..a7acb62f2 100644 --- a/include/cantera/base/AnyMap.h +++ b/include/cantera/base/AnyMap.h @@ -102,6 +102,21 @@ private: static std::map s_typenames; }; +// Implicit conversion of long int to double if accessed as a vector +template<> +const std::vector& AnyValue::asVector() const; + +template<> +std::vector& AnyValue::asVector(); + +// Implicit conversion of long int to double if accessed as a vector> +template<> +const std::vector& AnyValue::asVector() const; + +template<> +std::vector& AnyValue::asVector(); + + //! A map of string keys to values whose type can vary at runtime /*! * Values in an AnyMap are held by instances of AnyValue. Instances of AnyMap diff --git a/src/base/AnyMap.cpp b/src/base/AnyMap.cpp index 907c0f6df..22c1272cf 100644 --- a/src/base/AnyMap.cpp +++ b/src/base/AnyMap.cpp @@ -301,7 +301,11 @@ AnyValue &AnyValue::operator=(double value) { } double AnyValue::asDouble() const { - return as(); + if (m_value->type() == typeid(long int)) { + return as(); + } else { + return as(); + } } AnyValue &AnyValue::operator=(bool value) { @@ -326,6 +330,7 @@ AnyValue &AnyValue::operator=(int value) { long int AnyValue::asInt() const { return as(); } + AnyValue& AnyValue::operator=(const AnyMap& value) { *m_value = value; return *this; @@ -345,6 +350,67 @@ std::string AnyValue::demangle(const std::type_info& type) const } } +// Explicit template specializations to allow certain conversions + +template<> +const std::vector& AnyValue::asVector() const +{ + if (is>()) { + std::vector v; + for (const auto& el : asVector()) { + v.push_back(el); + } + *m_value = v; + } + return as>(); +} + +template<> +std::vector& AnyValue::asVector() +{ + if (is>()) { + std::vector v; + for (const auto& el : asVector()) { + v.push_back(el); + } + *m_value = v; + } + return as>(); +} + +template<> +const std::vector& AnyValue::asVector() const +{ + if (is>>()) { + std::vector v; + for (const auto& outer : asVector>()) { + v.push_back(vector_fp()); + for (const auto& inner : outer) { + v.back().push_back(inner); + } + } + *m_value = v; + } + return as>(); +} + +template<> +std::vector& AnyValue::asVector() +{ + if (is>>()) { + std::vector v; + for (const auto& outer : asVector>()) { + v.push_back(vector_fp()); + for (const auto& inner : outer) { + v.back().push_back(inner); + } + } + *m_value = v; + } + return as>(); +} + + // Methods of class AnyMap AnyValue& AnyMap::operator[](const std::string& key) diff --git a/test/general/test_containers.cpp b/test/general/test_containers.cpp index 934586bbb..a51cf927d 100644 --- a/test/general/test_containers.cpp +++ b/test/general/test_containers.cpp @@ -89,6 +89,19 @@ TEST(AnyMap, vector) EXPECT_EQ(m["nested/item"].asVector().size(), (size_t) 4); } +TEST(AnyMap, conversion_to_double) +{ + AnyMap m = AnyMap::fromYamlString( + "{scalar: 8, list: [7, 4, 1], nested: [[3, 4, 5], [12, 22, 91]]}"); + const AnyMap n = m; + EXPECT_EQ(m["scalar"].asDouble(), 8); + EXPECT_EQ(m["list"].asVector()[1], 4); + EXPECT_EQ(m["nested"].asVector()[1][2], 91); + EXPECT_EQ(n.at("scalar").asDouble(), 8); + EXPECT_EQ(n.at("list").asVector()[0], 7); + EXPECT_EQ(n.at("nested").asVector()[0][2], 5); +} + TEST(AnyMap, loadYaml) { AnyMap m = AnyMap::fromYamlString(