Given this code:
void LoadFromYaml(const YAML::Node& node){
const YAML::Node& Data=node["Data"];
if(Data){
if(Data.ValueIsInt)// Do something with integer.
if(Data.ValueIsFloat)// Do something with float.
if(Data.ValueIsString)// Do something with string.
}
}
How do I check is the data contained in the YAML Node 'Data' is an integer, float, or a string? Note: I don't want to check if the Node is a scalar, map, sequence, etc.
You can try to convert the node to each type:
try {
int value = data.as<int>();
// do something
} catch (const BadConversion& e) {
// do something else
}
Throwing lots of exceptions while parsing can impact your parsing speed. Not sure why yamlcpp
doesn't have an is_type<T>
method or something similar to std::optional
or std::expected
getters
Hacky way to get around it though with Boost - injecting your own template specialisation into the YAML
namespace and return boost::optional
(or std::optional
if you have C++17)
namespace YAML
{
template <typename T>
struct as_if<T, boost::optional<T> >
{
explicit as_if(const Node& node_) : node(node_) {}
const Node& node;
const boost::optional<T> operator()() const
{
boost::optional<T> val;
T t;
if (node.m_pNode && convert<T>::decode(node, t))
val = std::move(t);
return val;
}
};
// There is already a std::string partial specialisation, so we need a full specialisation here
template <>
struct as_if<std::string, boost::optional<std::string> >
{
explicit as_if(const Node& node_) : node(node_) {}
const Node& node;
const boost::optional<std::string> operator()() const
{
boost::optional<std::string> val;
std::string t;
if (node.m_pNode && convert<std::string>::decode(node, t))
val = std::move(t);
return val;
}
};
}
You can then run something like
boost::optional<bool> as_bool = YAML::as_if<bool, boost::optional<bool> >(node)();
boost::optional<int> as_int = YAML::as_if<int, boost::optional<int> >(node)();
boost::optional<double> as_double = YAML::as_if<double, boost::optional<double> >(node)();
boost::optional<std::string> as_string = YAML::as_if<std::string, boost::optional<std::string> >(node)();
Total cost of construction here is 4 optional values + 4 default values. This may or may not be faster than dealing with the exceptions, I haven't tested.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With