Allow AnyValue to convert implicitly from long int to double

This commit is contained in:
Ray Speth 2018-01-23 11:24:28 -05:00
parent 00f6b88fa4
commit e5bd0b136f
3 changed files with 95 additions and 1 deletions

View file

@ -102,6 +102,21 @@ private:
static std::map<std::string, std::string> s_typenames;
};
// Implicit conversion of long int to double if accessed as a vector<double>
template<>
const std::vector<double>& AnyValue::asVector<double>() const;
template<>
std::vector<double>& AnyValue::asVector<double>();
// Implicit conversion of long int to double if accessed as a vector<vector<double>>
template<>
const std::vector<vector_fp>& AnyValue::asVector<vector_fp>() const;
template<>
std::vector<vector_fp>& AnyValue::asVector<vector_fp>();
//! 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

View file

@ -301,7 +301,11 @@ AnyValue &AnyValue::operator=(double value) {
}
double AnyValue::asDouble() const {
return as<double>();
if (m_value->type() == typeid(long int)) {
return as<long int>();
} else {
return as<double>();
}
}
AnyValue &AnyValue::operator=(bool value) {
@ -326,6 +330,7 @@ AnyValue &AnyValue::operator=(int value) {
long int AnyValue::asInt() const {
return as<long int>();
}
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<double>& AnyValue::asVector<double>() const
{
if (is<std::vector<long int>>()) {
std::vector<double> v;
for (const auto& el : asVector<long int>()) {
v.push_back(el);
}
*m_value = v;
}
return as<std::vector<double>>();
}
template<>
std::vector<double>& AnyValue::asVector<double>()
{
if (is<std::vector<long int>>()) {
std::vector<double> v;
for (const auto& el : asVector<long int>()) {
v.push_back(el);
}
*m_value = v;
}
return as<std::vector<double>>();
}
template<>
const std::vector<vector_fp>& AnyValue::asVector<vector_fp>() const
{
if (is<std::vector<std::vector<long int>>>()) {
std::vector<vector_fp> v;
for (const auto& outer : asVector<std::vector<long int>>()) {
v.push_back(vector_fp());
for (const auto& inner : outer) {
v.back().push_back(inner);
}
}
*m_value = v;
}
return as<std::vector<vector_fp>>();
}
template<>
std::vector<vector_fp>& AnyValue::asVector<vector_fp>()
{
if (is<std::vector<std::vector<long int>>>()) {
std::vector<vector_fp> v;
for (const auto& outer : asVector<std::vector<long int>>()) {
v.push_back(vector_fp());
for (const auto& inner : outer) {
v.back().push_back(inner);
}
}
*m_value = v;
}
return as<std::vector<vector_fp>>();
}
// Methods of class AnyMap
AnyValue& AnyMap::operator[](const std::string& key)

View file

@ -89,6 +89,19 @@ TEST(AnyMap, vector)
EXPECT_EQ(m["nested/item"].asVector<double>().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<double>()[1], 4);
EXPECT_EQ(m["nested"].asVector<vector_fp>()[1][2], 91);
EXPECT_EQ(n.at("scalar").asDouble(), 8);
EXPECT_EQ(n.at("list").asVector<double>()[0], 7);
EXPECT_EQ(n.at("nested").asVector<vector_fp>()[0][2], 5);
}
TEST(AnyMap, loadYaml)
{
AnyMap m = AnyMap::fromYamlString(