ここでは、C ++タプル(
tuple )の操作について説明し、
タプルを使用するときの生活を大幅に簡素化できる便利な関数を提供し、これらの関数の使用例を示します。 個人的な経験からすべて。
Foreach
タプルのすべての要素を調べ、それぞれに対して同じ関数を呼び出すことは、おそらくタプルを使用するときに開発者が直面する最初のタスクです。 実装は非常に簡単です。
namespace tuple_utils {
ここでは、補助的な
_foreach_構造が
使用され、追加のテンプレートパラメーターとして別のタプルインデックスがあります。 唯一の静的メソッド
tupleForeach_は、このインデックスを持つ要素の
コールバックを介して指定された関数を呼び出し、その後、再帰的に呼び出されます。 ゼロに等しいインデックスに対するこの構造の部分的な特殊化は縮退であり、再帰の完了です。
例1.バナル struct ForeachCallback { template<std::size_t Index, class T> void operator()( T&& element ) { std::cout << "( " << Index << " : " << element << " ) "; } }; void foo() { auto myTyple = std::make_tuple( 42, 3.14, "boo" ); tuple_utils::tupleForeach( ForeachCallback(), myTyple ); }
地図
タプルの操作の利便性のために頭に浮かぶもう1つのタスクは、特定のタプルの要素に対する特定の関数の実行結果から新しいタプルを順番に作成する関数です。 関数型言語の非常に一般的なタスク。 その実装はおそらくもっと簡単です:
namespace tuple_utils {
ここで、補助関数
mapTuple_を使用します。これは、
index_sequenceを介して 、追加のパラメーター、すべてのタプルインデックスのセットを
受け取ります。 結果タプルは、各インデックスの要素に対する
コールバックを介して指定された関数の結果から形成されます。
例1.バナル struct MapCallback { template<std::size_t Index, class T> std::string operator()( T&& element ) { std::stringstream ss; ss << "( " << Index << " : " << element << " )"; std::string result; result << ss; return result; } }; void foo() { auto sourceTyple = std::make_tuple( 42, 3.14, "boo" ); auto strTuple = tuple_utils::mapTuple( MapCallback(), sourceTyple ); }
電話する
タプルで他にできることは、関数を呼び出すためのパラメーターとしてそのコンテンツを使用することです(当然、タプルの要素の順序とタイプに対応する引数の順序とタイプ)。 この関数の実装は、
map関数の実装に非常に似ています。
namespace tuple_utils {
ここでは、
mapの場合と同様に、補助関数
callTuple_が
使用されます 。これは、
index_sequenceを介して、追加のパラメーター、すべてのタプルインデックスのセットを
受け取ります。
callbackを介して指定された関数を呼び出し、インデックスに対応するすべてのタプル要素を渡します。 その実行の結果は、転送された関数の実行の結果です。
例1.バナル bool checkSomething( int a, float b, const std::string& txt ); struct CallCallback { template<class TResult, class ...TParams> TResult operator()( TParams... params ) { return checkSomething( params... ); } }; void foo() { std::tuple<int, float, std::string> paramsTyple = std::make_tuple( 42, 3.14, "boo" ); bool isParamsValid = tuple_utils::callTuple( CallCallback(), paramsTyple ); }
例2. getterパラメーター値を使用してsetterを呼び出す PS C ++ 17では、
std :: applyが利用可能になり、同じ機能を実行します。
総論
- インデックスをコールバックに渡す
上記の実装では、 コールバックによって処理される要素のインデックスがcallbackに渡されます 。 さらに、引数としてではなく、 コールバック自体のパラメーターとして渡されました。 これは、機能の範囲を拡張するためだけに行われます。 このような転送により、 コールバック内でテンプレート関数を呼び出し(パラメーターとしてインデックスを使用)、一般にインデックスをパラメーターとして使用して、インデックスを関数に引数として渡すときに不可能なものをインスタンス化できます。 - コールバック送信
上記のすべての実装では、 コールバックは参照によって(値ではなく) 渡されます。 これは、呼び出し元が使用する特定のコールバック (コピーではなく) の有効期間を制御するために行われます 。
別の例。 メソッドハンドラーからファンクターハンドラーへの変換 index_sequenceを使用しない実装
index_sequenceは、C ++ 14でのみ表示されます。 これらの関数をC ++ 11(タプルが現れた)で使用したい場合、何らかの他の理由で
index_sequenceを使用したくない場合、または
mapの実装を見てそれらなしで関数を
呼び出すのが面白い場合、実装は次のとおりです。
これらの関数の実装へのアプローチは同じです:インデックス(
index_sequenceの代わりに)またはパラメーターを手動で「蓄積」し、再帰の最後に、既に取得したインデックス/パラメーターのセットで必要なアクションを実行します。 個人的には、インデックスを使用したアプローチはより普遍的です。
お時間をいただきありがとうございます!