Partial pimpl for AnyValue to hide boost on API.

- boost now only included in AnyMap.inl.h (within include/cantera)
This commit is contained in:
Evan McCorkle 2017-10-22 14:05:55 -04:00 committed by Ray Speth
parent f8d183220c
commit 686250e51f
3 changed files with 69 additions and 28 deletions

View file

@ -7,13 +7,16 @@
#include "cantera/base/global.h"
#include "cantera/base/ctexceptions.h"
#include <boost/any.hpp>
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
namespace boost
{
class any;
}
namespace Cantera
{
@ -32,6 +35,13 @@ class AnyMap;
class AnyValue
{
public:
AnyValue();
~AnyValue();
AnyValue(AnyValue const& other);
AnyValue(AnyValue&& other);
AnyValue& operator=(AnyValue const& other);
AnyValue& operator=(AnyValue&& other);
AnyValue& operator[](const std::string& key);
bool hasKey(const std::string& key) const;
@ -88,7 +98,7 @@ private:
std::string demangle(const std::type_info& type) const;
std::string m_key;
boost::any m_value;
std::unique_ptr<boost::any> m_value;
static std::map<std::string, std::string> s_typenames;
};

View file

@ -16,15 +16,15 @@ namespace Cantera
template<class T>
const T &AnyValue::as() const {
try {
return boost::any_cast<const T&>(m_value);
return boost::any_cast<const T&>(*m_value);
} catch (boost::bad_any_cast&) {
if (m_value.type() == typeid(void)) {
if (m_value->type() == typeid(void)) {
// Values that have not been set are of type 'void'
throw CanteraError("AnyValue::as", "Key '{}' not found", m_key);
} else {
throw CanteraError("AnyValue::as",
"Key '{}' contains a '{}',\nnot a '{}'.",
m_key, demangle(m_value.type()), demangle(typeid(T)));
m_key, demangle(m_value->type()), demangle(typeid(T)));
}
}
}
@ -32,27 +32,27 @@ const T &AnyValue::as() const {
template<class T>
T &AnyValue::as() {
try {
return boost::any_cast<T&>(m_value);
return boost::any_cast<T&>(*m_value);
} catch (boost::bad_any_cast&) {
if (m_value.type() == typeid(void)) {
if (m_value->type() == typeid(void)) {
// Values that have not been set are of type 'void'
throw CanteraError("AnyValue::as", "Key '{}' not found", m_key);
} else {
throw CanteraError("AnyValue::as",
"Key '{}' contains a '{}',\nnot a '{}'.",
m_key, demangle(m_value.type()), demangle(typeid(T)));
m_key, demangle(m_value->type()), demangle(typeid(T)));
}
}
}
template<class T>
bool AnyValue::is() const {
return m_value.type() == typeid(T);
return m_value->type() == typeid(T);
}
template<class T>
AnyValue &AnyValue::operator=(const std::vector<T> &value) {
m_value = value;
*m_value = value;
return *this;
}
@ -68,7 +68,7 @@ std::vector<T> &AnyValue::asVector() {
template<class T>
AnyValue& AnyValue::operator=(const std::unordered_map<std::string, T> items) {
m_value = AnyMap();
*m_value = AnyMap();
AnyMap& dest = as<AnyMap>();
for (const auto& item : items) {
dest[item.first] = item.second;
@ -78,7 +78,7 @@ AnyValue& AnyValue::operator=(const std::unordered_map<std::string, T> items) {
template<class T>
AnyValue& AnyValue::operator=(const std::map<std::string, T> items) {
m_value = AnyMap();
*m_value = AnyMap();
AnyMap& dest = as<AnyMap>();
for (const auto& item : items) {
dest[item.first] = item.second;
@ -91,14 +91,14 @@ inline AnyMap& AnyValue::as<AnyMap>() {
try {
// This is where nested AnyMaps are created when the syntax
// m[key1][key2] is used.
if (m_value.type() == typeid(void)) {
m_value = AnyMap();
if (m_value->type() == typeid(void)) {
*m_value = AnyMap();
}
return boost::any_cast<AnyMap&>(m_value);
return boost::any_cast<AnyMap&>(*m_value);
} catch (boost::bad_any_cast&) {
throw CanteraError("AnyValue::as",
"value of key '{}' is a '{}',\nnot an 'AnyMap'.",
m_key, demangle(m_value.type()));
m_key, demangle(m_value->type()));
}
}
@ -108,7 +108,7 @@ std::map<std::string, T> AnyValue::asMap()
std::map<std::string, T> dest;
for (const auto& item : as<AnyMap>().m_data) {
try {
dest[item.first] = boost::any_cast<T>(item.second.m_value);
dest[item.first] = boost::any_cast<T>(*item.second.m_value);
} catch (boost::bad_any_cast&) {
throw CanteraError("AnyValue::asMap",
"Value of key '{}' is not a '{}'",

View file

@ -17,6 +17,37 @@ std::map<std::string, std::string> AnyValue::s_typenames = {
// Methods of class AnyValue
AnyValue::AnyValue()
: m_key()
, m_value(new boost::any{})
{}
AnyValue::~AnyValue() = default;
AnyValue::AnyValue(AnyValue const& other): m_key(other.m_key),
m_value(new boost::any{*other.m_value}) {
}
AnyValue::AnyValue(AnyValue&& other): m_key(std::move(other.m_key)),
m_value(std::move(other.m_value)) {
}
AnyValue& AnyValue::operator=(AnyValue const& other) {
if (this == &other)
return *this;
m_key = other.m_key;
m_value.reset(new boost::any{*other.m_value});
return *this;
}
AnyValue& AnyValue::operator=(AnyValue&& other) {
if (this == &other)
return *this;
m_key = std::move(other.m_key);
m_value = std::move(other.m_value);
return *this;
}
AnyValue& AnyValue::operator[](const std::string& key)
{
return as<AnyMap>()[key];
@ -29,16 +60,16 @@ bool AnyValue::hasKey(const std::string& key) const {
void AnyValue::setKey(const std::string &key) { m_key = key; }
const std::type_info &AnyValue::type() {
return m_value.type();
return m_value->type();
}
AnyValue &AnyValue::operator=(const std::string &value) {
m_value = value;
*m_value = value;
return *this;
}
AnyValue &AnyValue::operator=(const char *value) {
m_value = std::string(value);
*m_value = std::string(value);
return *this;
}
@ -47,7 +78,7 @@ const std::string &AnyValue::asString() const {
}
AnyValue &AnyValue::operator=(double value) {
m_value = value;
*m_value = value;
return *this;
}
@ -56,7 +87,7 @@ double AnyValue::asDouble() const {
}
AnyValue &AnyValue::operator=(bool value) {
m_value = value;
*m_value = value;
return *this;
}
@ -65,12 +96,12 @@ bool AnyValue::asBool() const {
}
AnyValue &AnyValue::operator=(long int value) {
m_value = value;
*m_value = value;
return *this;
}
AnyValue &AnyValue::operator=(int value) {
m_value = static_cast<long int>(value);
*m_value = static_cast<long int>(value);
return *this;
}
@ -78,12 +109,12 @@ long int AnyValue::asInt() const {
return as<long int>();
}
AnyValue& AnyValue::operator=(const AnyMap& value) {
m_value = value;
*m_value = value;
return *this;
}
AnyValue& AnyValue::operator=(AnyMap&& value) {
m_value = std::move(value);
*m_value = std::move(value);
return *this;
}