Implementation:Onnx Onnx Proto Visitor
| Knowledge Sources | |
|---|---|
| Domains | Design Patterns, Graph Traversal |
| Last Updated | 2026-02-10 00:00 GMT |
Overview
Concrete tool for traversing ONNX protobuf graph structures using the visitor pattern provided by the ONNX library.
Description
The onnx/common/visitor.h header provides two visitor pattern implementations for traversing ONNX protobuf structures: a read-only Visitor and a mutation-capable MutableVisitor. Both reside in the ONNX_NAMESPACE::internal namespace.
Visitor (read-only) provides virtual methods in two categories:
- VisitX methods (VisitGraph, VisitFunction, VisitNode, VisitAttribute) that orchestrate traversal. Each VisitX method calls the corresponding ProcessX method and, if it returns true, recursively visits all children.
- ProcessX methods (ProcessGraph, ProcessFunction, ProcessNode, ProcessAttribute) that serve as callbacks for subclasses to override. They return bool to control whether traversal continues into children. All default to returning true (continue traversal).
The traversal hierarchy is: Graph/Function contains Nodes; Nodes contain Attributes; Attributes may contain sub-Graphs (via attr.g() for single graphs or attr.graphs() for multiple graphs). This enables recursive traversal of nested subgraphs within control flow operators like If and Loop.
MutableVisitor mirrors the same structure but takes pointers instead of const references, allowing modifications to the visited protobuf objects. It uses mutable_node(), mutable_attribute(), mutable_g(), and mutable_graphs() for write access to protobuf fields.
Both classes have virtual destructors for safe polymorphic use.
Usage
Use Visitor when you need to analyze or inspect an ONNX graph without modifying it. Use MutableVisitor when you need to transform graph elements in place. Subclass the appropriate visitor and override the ProcessX methods to implement your specific logic. Return false from a ProcessX method to skip traversal of that element's children.
Code Reference
Source Location
- Repository: Onnx_Onnx
- File: onnx/common/visitor.h
Signature
namespace ONNX_NAMESPACE {
namespace internal {
struct Visitor {
virtual void VisitGraph(const GraphProto& graph);
virtual void VisitFunction(const FunctionProto& function);
virtual void VisitNode(const NodeProto& node);
virtual void VisitAttribute(const AttributeProto& attr);
virtual bool ProcessGraph(const GraphProto& graph);
virtual bool ProcessFunction(const FunctionProto& function);
virtual bool ProcessNode(const NodeProto& node);
virtual bool ProcessAttribute(const AttributeProto& attr);
virtual ~Visitor() = default;
};
struct MutableVisitor {
virtual void VisitGraph(GraphProto* graph);
virtual void VisitFunction(FunctionProto* function);
virtual void VisitNode(NodeProto* node);
virtual void VisitAttribute(AttributeProto* attr);
virtual bool ProcessGraph(GraphProto* graph);
virtual bool ProcessFunction(FunctionProto* function);
virtual bool ProcessNode(NodeProto* node);
virtual bool ProcessAttribute(AttributeProto* attr);
virtual ~MutableVisitor() = default;
};
} // namespace internal
} // namespace ONNX_NAMESPACE
Import
#include "onnx/common/visitor.h"
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| graph | const GraphProto& (Visitor) or GraphProto* (MutableVisitor) | Yes | The root graph to begin traversal from |
| function | const FunctionProto& or FunctionProto* | Yes (alternative) | A function to begin traversal from |
Outputs
| Name | Type | Description |
|---|---|---|
| ProcessX return | bool | Controls traversal: true continues into children, false skips children |
| (side effects) | varies | Subclass-defined behavior via overridden ProcessX methods |
Usage Examples
#include "onnx/common/visitor.h"
using namespace ONNX_NAMESPACE;
// Read-only visitor to count nodes
struct NodeCounter : internal::Visitor {
int count = 0;
bool ProcessNode(const NodeProto& node) override {
count++;
return true; // continue visiting attributes/subgraphs
}
};
NodeCounter counter;
counter.VisitGraph(model.graph());
std::cout << "Total nodes: " << counter.count << std::endl;
// Mutable visitor to rename operators
struct OpRenamer : internal::MutableVisitor {
bool ProcessNode(NodeProto* node) override {
if (node->op_type() == "OldName") {
node->set_op_type("NewName");
}
return true; // continue into subgraphs
}
};
OpRenamer renamer;
renamer.VisitGraph(model.mutable_graph());
// Visitor that skips subgraph traversal
struct TopLevelOnly : internal::Visitor {
bool ProcessAttribute(const AttributeProto& attr) override {
return false; // do not recurse into subgraphs within attributes
}
bool ProcessNode(const NodeProto& node) override {
// only processes top-level nodes
return true;
}
};