ビジター パターンを使用した C++ 配列上での演算
C++ MATLAB® データ API は、関数 matlab::data::apply_visitor
および matlab::data::apply_visitor_ref
を介したビジター クラスの使用をサポートします。これらの関数は配列または配列参照およびビジター クラスを入力として受け入れます。
関数 apply_visitor
および apply_visitor_ref
は、入力配列型に基づいてビジター クラスで定義された演算にディスパッチします。ビジター クラスは特定の配列型で実行する演算を定義します。
以下のような場合にビジター パターンを使用します。
配列上で多数の演算を実行する必要があり、実行方法が配列の型によって異なる。
関数から返される配列は異なる既知の型になる可能性があるが、すべてのケースを処理する必要がある。
cell 配列や構造体配列のような異種混合の構造体で作業をしている。
配列または配列参照へのディスパッチ
関数 apply_visitor
は入力配列の型に基づいてビジター クラスの演算にディスパッチします。apply_visitor
を呼び出す構文は matlab::data::Array
とビジター クラス インスタンスを受け入れます。
auto apply_visitor(matlab::data::Array a, V visitor)
関数 apply_visitor_ref
は、入力として渡された配列参照の型に基づいてビジター クラスの演算にディスパッチします。apply_visitor_ref
を呼び出す構文は matlab::data::ArrayRef
とビジター クラス インスタンスを受け入れます。
auto apply_visitor_ref(const matlab::data::ArrayRef& a, V visitor)
operator()
のオーバーロード
演算を行う配列型の演算子 operator()
をオーバーロードするには、ビジター クラスを実装します。たとえば、実装する演算の 1 つが、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
ループで要素参照を使用しなければなりません。
cell 配列の内容を表示するビジター クラス
この例では、ビジター クラスを使用して matlab::data::Array
の特定の型に対して実行する演算を定義する方法を示します。
DisplayVisitor
クラスは、配列型が bool
、double
、char
の cell 配列の内容、およびそこに含まれている cell 配列を表示するための演算を実装します。オーバーロードされた関数をさらに追加して、他の cell 配列の内容をサポートする新しい演算を追加できます。
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); } }
クラスを使用するには、cell 配列を関数 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; }
cell 配列の内容を変更するビジター クラス
この例では、CellModifyVisitor
クラスは、型が bool
、double
、char
の cell 配列の内容、およびそこに含まれている cell 配列を変更するための演算を実装します。オーバーロードされた関数をさらに追加して、他の cell 配列の内容をサポートする新しい演算を追加できます。
関数 ModifyCell
は、ループ内で cell 配列の各要素に対して apply_visitor_ref
を呼び出します。ここでは cell 配列の内容を変更することが目的であるため、この例では cell 配列の内容への参照を使用します。
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); } }
クラスを使用するには、cell 配列を関数 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; }
参考
matlab::data::apply_visitor
| matlab::data::apply_visitor_ref