Operate on C++ Arrays Using Visitor Pattern
The C++ MATLAB® Data API supports the use of visitor classes via the matlab::data::apply_visitor
and matlab::data::apply_visitor_ref
functions. These functions accept an array or
array reference and a visitor class as inputs.
The apply_visitor
and apply_visitor_ref
functions dispatch to the operations defined by the visitor class based on input array
type. The visitor class defines operations to perform on specific types of array.
Use the visitor pattern in cases such as these:
There are many operations that you need to perform on an array and the way to perform them depends on the type of the array.
The array returned by a function can be of different known types and you want to handle all cases.
You are working with heterogeneous structures like cell arrays or structure arrays.
Dispatch on Array or Array Reference
The apply_visitor
function dispatches to the visitor class
operation based on the type of the input array. The syntax for calling
apply_visitor
accepts a
matlab::data::Array
and your visitor class instance:
auto apply_visitor(matlab::data::Array a, V visitor)
The apply_visitor_ref
function dispatches to the visitor class
operation based on the type of the array reference passed as an input. The syntax
for calling apply_visitor_ref
accepts a
matlab::data::ArrayRef
and your visitor class
instance:
auto apply_visitor_ref(const matlab::data::ArrayRef& a, V visitor)
Overloading operator()
Implement your visitor class to overload the operator
operator()
for the array types you want to operate on. For
example, suppose one operation that you want to implement is to return the text
contained in a matlab::data::CharArray
as a
std::string
. Implement the operation like this:
std::string operator()(matlab::data::CharArray arr){ return arr.toAscii(); }
As another example, suppose that you want to negate the logical values in a
matlab::data::TypedArray
. In this case, use a reference to
the array:
void operator()(TypedArrayRef<bool> boolArrRef) { std::cout << "Negate logical value: " << std::endl; for (auto &b : boolArrRef) { b = !b; } }
You must use an element reference in the range-based for
loop
to change the value in the array. Only use
matlab::data::TypedArrayRef
on elements of a container type
such as a struct or cell.
Visitor Class to Display Contents of Cell Array
This example shows how to use a visitor class to define operations to perform on specific types of matlab::data::Array
.
The DisplayVisitor
class implements operations to display the contents of cell arrays for arrays of types bool
, double
, and char
, and contained cell arrays. You can add new operations to support other cell array contents by adding more overloaded functions.
type DisplayVisitor.cpp
#include "MatlabDataArray.hpp" #include <iostream> using namespace matlab::data; void DisplayCell(const CellArray cellArray); class DisplayVisitor { public: template <typename U> void operator()(U arr) {} void operator()(const TypedArray<bool> boolArr) { std::cout << "Cell contains logical array: " << std::endl; for (auto b : boolArr) { printf_s("%d ", b); } std::cout << "\n"; } void operator()(const TypedArray<double> doubleArr) { std::cout << "Cell contains double array: " << std::endl; for (auto elem : doubleArr) { std::cout << elem << " "; } std::cout << "\n"; } void operator()(const CharArray charArr) { std::cout << "Cell contains char array: " << std::endl; for (auto elem : charArr) { std::cout << char(elem); } std::cout << "\n"; } void operator()(const CellArray containedCellArray) { DisplayCell(containedCellArray); } }; void DisplayCell(const CellArray cellArray) { DisplayVisitor v; for (auto elem : cellArray) { apply_visitor(elem, v); } }
To use the class, pass a cell array to the DisplayCell
function.
type callDisplayCell.cpp
int main() { ArrayFactory factory; // Create cell array matlab::data::CellArray cellArray = factory.createCellArray({ 1,4 }, factory.createCharArray("A char array"), factory.createArray<bool>({ 1,2 }, { false, true }), factory.createArray<double>({ 2,2 }, { 1.2, 2.2, 3.2, 4.2 }), factory.createCellArray({ 1,1 }, false)); // Call function DisplayCell(cellArray); return 0; }
Visitor Class to Modify Contents of Cell Array
In this example, the CellModifyVisitor
class implements the operations to modify the contents of cell arrays of types bool
, double
, and char
, and contained cell arrays. You can add new operations to support other cell array contents by adding more overloaded functions.
The ModifyCell
function calls apply_visitor_ref
in a loop for each element in the cell array. Because the objective is to modify the contents of the cell array, this example uses references to the cell array contents.
type CellModifyVisitor.cpp
#include "MatlabDataArray.hpp" #include "MatlabEngine.hpp" #include <iostream> using namespace matlab::data; void ModifyCell(CellArray &cellArray); class CellModifyVisitor { public: template <typename U> void operator()(U arr) {} void operator()(TypedArrayRef<bool> boolArrRef) { std::cout << "Negate logical value: " << std::endl; for (auto &b : boolArrRef) { b = !b; } } void operator()(TypedArrayRef<double> doubleArrRef) { std::cout << "Add 1 to each value: " << std::endl; for (auto &elem : doubleArrRef) { elem = elem + 1; } std::cout << "\n"; } void operator()(CharArrayRef charArrRef) { std::cout << "Modify char array" << std::endl; ArrayFactory factory; charArrRef = factory.createCharArray("Modified char array"); } void operator()(CellArrayRef containedCellArray) { CellModifyVisitor v; for (auto elem : containedCellArray) { apply_visitor_ref(elem, v); } } }; void ModifyCell(CellArray &cellArray) { CellModifyVisitor v; for (auto elem : cellArray) { apply_visitor_ref(elem, v); } }
To use the class, pass a cell array to the ModifyCell
function.
type callModifyCell.cpp
int main() { ArrayFactory factory; // Create cell array matlab::data::CellArray cellArray = factory.createCellArray({ 1,4 }, factory.createCharArray("A char array"), factory.createArray<bool>({ 1,2 }, { false, true }), factory.createArray<double>({ 2,2 }, { 1.2, 2.2, 3.2, 4.2 }), factory.createCellArray({ 1,1 }, false)); // Call function ModifyCell(cellArray); return 0; }
See Also
matlab::data::apply_visitor
| matlab::data::apply_visitor_ref