From 530adbb93110859c854c9ab5667c3672384a51e1 Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Tue, 30 Jan 2018 15:01:06 -0500 Subject: [PATCH] Add automatic conversions to vector --- include/cantera/base/AnyMap.h | 11 +++++++++ src/base/AnyMap.cpp | 42 ++++++++++++++++++++++++++++++++ test/general/test_containers.cpp | 12 +++++++++ 3 files changed, 65 insertions(+) diff --git a/include/cantera/base/AnyMap.h b/include/cantera/base/AnyMap.h index a7acb62f2..dfccc5e81 100644 --- a/include/cantera/base/AnyMap.h +++ b/include/cantera/base/AnyMap.h @@ -61,16 +61,20 @@ public: template bool is() const; + explicit AnyValue(const std::string& value); AnyValue& operator=(const std::string& value); AnyValue& operator=(const char* value); const std::string& asString() const; + explicit AnyValue(double value); AnyValue& operator=(double value); double asDouble() const; + explicit AnyValue(bool value); AnyValue& operator=(bool value); bool asBool() const; + explicit AnyValue(long int value); AnyValue& operator=(long int value); AnyValue& operator=(int value); long int asInt() const; @@ -102,6 +106,13 @@ private: static std::map s_typenames; }; +// Implicit conversion to 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; diff --git a/src/base/AnyMap.cpp b/src/base/AnyMap.cpp index 22c1272cf..6958d06fd 100644 --- a/src/base/AnyMap.cpp +++ b/src/base/AnyMap.cpp @@ -281,6 +281,8 @@ const std::type_info &AnyValue::type() { return m_value->type(); } +AnyValue::AnyValue(const std::string& value) : m_value(new boost::any{value}) {} + AnyValue &AnyValue::operator=(const std::string &value) { *m_value = value; return *this; @@ -295,6 +297,8 @@ const std::string &AnyValue::asString() const { return as(); } +AnyValue::AnyValue(double value) : m_value(new boost::any{value}) {} + AnyValue &AnyValue::operator=(double value) { *m_value = value; return *this; @@ -308,6 +312,8 @@ double AnyValue::asDouble() const { } } +AnyValue::AnyValue(bool value) : m_value(new boost::any{value}) {} + AnyValue &AnyValue::operator=(bool value) { *m_value = value; return *this; @@ -317,6 +323,8 @@ bool AnyValue::asBool() const { return as(); } +AnyValue::AnyValue(long int value) : m_value(new boost::any{value}) {} + AnyValue &AnyValue::operator=(long int value) { *m_value = value; return *this; @@ -352,6 +360,40 @@ 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; + if (is>()) { + for (const auto& el : asVector()) { + v.push_back(AnyValue(el)); + } + *m_value = v; + } else if (is>()) { + for (const auto& el : asVector()) { + v.push_back(AnyValue(el)); + } + *m_value = v; + } else if (is>()) { + for (const auto& el : asVector()) { + v.push_back(AnyValue(el)); + } + *m_value = v; + } + // If none of these special cases match, the value won't be replaced, + // and an exception will be thrown. + } + return as>(); +} + +template<> +std::vector& AnyValue::asVector() +{ + return const_cast&>( + const_cast(this)->asVector()); +} + template<> const std::vector& AnyValue::asVector() const { diff --git a/test/general/test_containers.cpp b/test/general/test_containers.cpp index a51cf927d..62a75fcd9 100644 --- a/test/general/test_containers.cpp +++ b/test/general/test_containers.cpp @@ -102,6 +102,18 @@ TEST(AnyMap, conversion_to_double) EXPECT_EQ(n.at("nested").asVector()[0][2], 5); } +TEST(AnyMap, conversion_to_anyvalue) +{ + AnyMap m = AnyMap::fromYamlString( + "{floats: [7.5, 40, -3.14], strings: [foo, bar]}"); + const AnyMap n = m; + EXPECT_EQ(m["floats"].asVector()[0].asDouble(), 7.5); + EXPECT_EQ(m["strings"].asVector()[1].asString(), "bar"); + EXPECT_EQ(n.at("floats").asVector()[2].asDouble(), -3.14); + EXPECT_EQ(n.at("strings").asVector()[0].asString(), "foo"); +} + + TEST(AnyMap, loadYaml) { AnyMap m = AnyMap::fromYamlString(