Работайте с массивами C++ Используя шаблон Visitor

MATLAB® Data API C++ поддерживает использование классов посетителя через функции matlab::data::apply_visitor_ref и matlab::data::apply_visitor. Эти функции принимают массив или ссылку на массив и visitor class как входные параметры.

apply_visitor и функции apply_visitor_ref отправляют операциям, заданным visitor class на основе типа входного массива. Visitor class задает операции, чтобы выполнить на определенных типах массива.

Используйте шаблон "посетитель" в случаях, таких как они:

  • Существует много операций, которые необходимо выполнить на массиве, и способ выполнить их зависит от типа массива.

  • Массив, возвращенный функцией, может иметь различные известные типы, и вы хотите обработать все случаи.

  • Вы работаете с гетерогенными структурами как массивы ячеек или массивы структур.

Диспетчеризация на ссылке на массив или ссылке на массив

Функция apply_visitor отправляет операции visitor class на основе типа входного массива. Синтаксис для вызова apply_visitor принимает matlab::data::Array и ваш экземпляр visitor class:

auto apply_visitor(matlab::data::Array a, V visitor)

Функция apply_visitor_ref отправляет операции visitor class на основе типа ссылки на массив, переданной как вход. Синтаксис для вызова apply_visitor_ref принимает matlab::data::ArrayRef и ваш экземпляр visitor class:

auto apply_visitor_ref(const matlab::data::ArrayRef& a, V visitor)

Перегрузка оператора ()

Реализуйте своего visitor class, чтобы перегрузить оператор operator() для типов массива, с которыми вы хотите работать. Например, предположите одну операцию, которую вы хотите реализовать, должен возвратить текст, содержавшийся в matlab::data::CharArray как std::string. Реализуйте операцию как это:

std::string operator()(matlab::data::CharArray arr){
   return arr.toAscii();
}

Как другой пример, предположите, что вы хотите инвертировать логические значения в matlab::data::TypedArray. В этом случае используйте ссылку на массив:

void operator()(TypedArrayRef<bool> boolArrRef) {
    std::cout << "Negate logical value: " << std::endl;
    for (auto &b : boolArrRef) {
        b = !b;
    }       
}

Необходимо использовать ссылку на элемент в основанном на области значений цикле for, чтобы изменить значение в массиве.

Класс Visitor, для отображения содержимого массива ячеек

Этот пример показывает, как использовать visitor class, чтобы задать операции, чтобы выполнить на определенных типах matlab::data::Array.

Класс DisplayVisitor реализует операции, чтобы отобразить содержимое массивов ячеек для массивов типов bool, double, и char и содержавшие массивы ячеек. Можно добавить новые операции, чтобы поддержать другое содержимое массива ячеек путем добавления большего количества перегруженных функций.

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);
        }
    }

Чтобы использовать класс, передайте массив ячеек функции DisplayCell.

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;
}

Класс посетителя, чтобы изменить содержимое массива ячеек

В этом примере класс CellModifyVisitor реализует операции, чтобы изменить содержимое массивов ячеек типов bool, double, и char и содержавшие массивы ячеек. Можно добавить новые операции, чтобы поддержать другое содержимое массива ячеек путем добавления большего количества перегруженных функций.

Вызовы функции ModifyCell apply_visitor_ref в цикле для каждого элемента в массиве ячеек. Поскольку цель состоит в том, чтобы изменить содержимое массива ячеек, этот пример использует ссылки на содержимое массива ячеек.

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);
    }
}

Чтобы использовать класс, передайте массив ячеек функции ModifyCell.

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;
}

Смотрите также

|

Похожие темы