The built-in C attribute handler in igraph supports numeric, boolean and string types only as these were the ones that were most commonly used in C. C++ is a different beast, and you would need to implement your own attribute handler for it.
The attribute handler is basically a table of functions that igraph calls whenever something relevant happens to your graph (nodes / edges are added, removed, permuted etc), and it is the responsibility of the functions in the attribute handler to update the data structures storing the attributes themselves. The full list of functions to implement in an attribute handler is here.
For instance, when you want to add new edges to a graph from C, you call
igraph_add_edges(graph, edges, attr) where
graph is the graph to be modified,
edges is the vector of vertex IDs that are used to build the new edges, and
attr is an opaque pointer that is used to encode the attributes corresponding to the edges.
igraph_add_edges() adds the edges themselves but it does nothing with
attr apart from forwarding it to the current attribute handler table. More precisely,
igraph_add_edges() calls the
add_edges() callback of the attribute handler with
attr after the edges themselves have been added to graph. It is up to you in the attribute handler to parse the contents of
attr and adjust the data structures used to store the attributes.
The “common”, language-agnostic part of the attribute handling is to be found in this file in the source code. The implementation of the C attribute handler is in this file. Internally, the C attribute handler stores the attributes in three
igraph_vector_ptr_t objects (one for graph, vertex and edge attributes, respectively), encapsulated in a
igraph_vector_ptr_t then contains a list of
igraph_attribute_record_t objects, one for each attribute; an attribute record contains the name of the attribute, the type of the attribute and the values for every vertex / edge. In C++, I would probably replace this completely with having three
std::map<std::string, ...> objects, mapping attribute names to some kind of struct that encapsulates the name and type of the attribute and an STL container to store the actual values. The lifecycle of attribute objects would then be managed by the STL container.