Operate on C++ Arrays Using Visitor Pattern - MATLAB & Simulink (original) (raw)

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:

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 callingapply_visitor accepts amatlab::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 amatlab::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 operatoroperator() 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 astd::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 amatlab::data::TypedArray. In this case, use a reference to the array:

void operator()(TypedArrayRef 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 usematlab::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.

#include "MatlabDataArray.hpp" #include

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.

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

using namespace matlab::data; void ModifyCell(CellArray &cellArray);

class CellModifyVisitor { public: template 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.

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

Topics