Converting YAML Nodes to C++ Types Using `as<T>()` in yaml-cpp
The as<T>() method converts a YAML::Node to any C++ type by delegating to template specializations of YAML::convert<T>, throwing YAML::BadConversion on failure.
yaml-cpp represents every element of a YAML document as a YAML::Node. The templated member function as<T>() provides the primary mechanism for extracting concrete C++ values from these nodes, supporting automatic conversions for scalars, STL containers, and user-defined types through explicit template specialization.
How as<T>() Works Under the Hood
In include/yaml-cpp/node/node.h (lines 65-68), the Node class declares the conversion interface:
template <typename T>
T as() const;
When you invoke node.as<T>(), the library forwards the request to the YAML::convert<T> struct. This two-way conversion mechanism relies on two static methods:
convert<T>::decode(const Node&, T&)– Reads the node’s contents and populates the supplied object.convert<T>::encode(const T&)– Creates aNodefrom a value of typeT.
The default specializations for standard library types—including scalar values, std::vector, std::list, std::map, and std::unordered_map—reside in include/yaml-cpp/node/convert.h (lines 279-385). Each specialization validates the node type (using methods like IsMap() or IsSequence()) and iterates over child nodes, recursively calling element.first.as<K>() and element.second.as<V>() for key-value pairs.
Converting Built-in and STL Types
The as<T>() method handles direct scalar extraction and automatic container conversion without requiring manual iteration.
Scalar Values
Extract primitive types directly from key-value pairs:
YAML::Node cfg = YAML::Load("{port: 8080, host: \"localhost\"}");
int port = cfg["port"].as<int>(); // -> 8080
std::string host = cfg["host"].as<std::string>(); // -> "localhost"
STL Containers
Convert sequences to vectors and maps to associative containers automatically:
// Sequence to std::vector<int>
YAML::Node numbers = YAML::Load("[1, 2, 3, 4]");
std::vector<int> vec = numbers.as<std::vector<int>>(); // {1,2,3,4}
// Map to std::map<std::string,double>
YAML::Node rates = YAML::Load("{USD: 1.0, EUR: 0.85}");
std::map<std::string,double> exchange = rates.as<std::map<std::string,double>>();
Handling Conversion Failures and Fallback Values
When type conversion fails, as<T>() throws YAML::BadConversion. To avoid exceptions, use the fallback overload declared in include/yaml-cpp/node/node.h (lines 66-68):
// Returns 80 if "missing_port" doesn't exist or cannot convert to int
int port = config["missing_port"].as<int>(80);
This overload returns the provided fallback value when the node is undefined or the conversion cannot be performed.
Creating Custom Type Conversions
Extend yaml-cpp to support your own types by specializing YAML::convert<T>. The template uses an as_if helper (declared as a friend in node.h) which selects the appropriate specialization at compile-time.
Here is a complete example for a 3D vector struct:
struct Vec3 { double x, y, z; };
namespace YAML {
template <> struct convert<Vec3> {
static Node encode(const Vec3& v) {
Node n(NodeType::Sequence);
n.push_back(v.x); n.push_back(v.y); n.push_back(v.z);
return n;
}
static bool decode(const Node& node, Vec3& v) {
if (!node.IsSequence() || node.size() != 3) return false;
v.x = node[0].as<double>();
v.y = node[1].as<double>();
v.z = node[2].as<double>();
return true;
}
};
}
// Usage
YAML::Node point = YAML::Load("[10.0, 20.5, -3.2]");
Vec3 v = point.as<Vec3>(); // v.x==10.0, v.y==20.5, v.z==-3.2
Place specializations in the YAML namespace before calling as<Vec3>().
Summary
as<T>()is defined ininclude/yaml-cpp/node/node.hand provides type-safe conversion fromYAML::Nodeto C++ types.- The conversion delegates to
YAML::convert<T>specializations, with defaults for scalars and STL containers ininclude/yaml-cpp/node/convert.h. - Failed conversions throw
YAML::BadConversion, but theas<T>(fallback)overload provides exception-safe defaults. - Custom types require specializing
YAML::convert<YourType>withencode()anddecode()methods.
Frequently Asked Questions
What happens if as<T>() fails to convert a node?
The method throws YAML::BadConversion, a subclass of YAML::Exception. This occurs when the node type does not match the requested C++ type or when a custom decode() implementation returns false.
How do I provide a default value when conversion might fail?
Use the fallback overload syntax: node.as<T>(default_value). According to the source in node.h (lines 66-68), this returns the supplied default if the node is undefined or the conversion fails, without throwing an exception.
Can I convert YAML sequences to STL containers like std::vector?
Yes. The default specialization in convert.h automatically handles std::vector, std::list, and other sequence containers by iterating over the node's children and recursively converting each element using the same as<T>() mechanism.
How do I add support for my own custom C++ types?
Specialize YAML::convert<YourType> in the YAML namespace. Implement a static decode(const Node&, YourType&) method that returns bool (true on success) and an optional encode(const YourType&) method for emitting YAML. The generic conversion logic in src/convert.cpp integrates these specializations at compile-time.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →