C++
std :: integer_sequence
サーチ…
前書き
クラステンプレート
std::integer_sequence<Type, Values...>
は、タイプType
の値のシーケンスを表します。 Type
は、組み込み整数タイプの1つです。これらのシーケンスは、位置アクセスの恩恵を受けるクラスまたは関数テンプレートを実装するときに使用されます。標準ライブラリには、要素数から整数値の昇順シーケンスを作成する「ファクトリ」型も含まれています。
std :: tupleを回す関数のパラメータに変換する
std::tuple<T...>
は、複数の値を渡すために使用できます。例えば、一連のパラメータを何らかの形式のキューに格納するために使用できます。このようなタプルを処理する場合、その要素を関数呼び出し引数に変換する必要があります。
#include <array>
#include <iostream>
#include <string>
#include <tuple>
#include <utility>
// ----------------------------------------------------------------------------
// Example functions to be called:
void f(int i, std::string const& s) {
std::cout << "f(" << i << ", " << s << ")\n";
}
void f(int i, double d, std::string const& s) {
std::cout << "f(" << i << ", " << d << ", " << s << ")\n";
}
void f(char c, int i, double d, std::string const& s) {
std::cout << "f(" << c << ", " << i << ", " << d << ", " << s << ")\n";
}
void f(int i, int j, int k) {
std::cout << "f(" << i << ", " << j << ", " << k << ")\n";
}
// ----------------------------------------------------------------------------
// The actual function expanding the tuple:
template <typename Tuple, std::size_t... I>
void process(Tuple const& tuple, std::index_sequence<I...>) {
f(std::get<I>(tuple)...);
}
// The interface to call. Sadly, it needs to dispatch to another function
// to deduce the sequence of indices created from std::make_index_sequence<N>
template <typename Tuple>
void process(Tuple const& tuple) {
process(tuple, std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
// ----------------------------------------------------------------------------
int main() {
process(std::make_tuple(1, 3.14, std::string("foo")));
process(std::make_tuple('a', 2, 2.71, std::string("bar")));
process(std::make_pair(3, std::string("pair")));
process(std::array<int, 3>{ 1, 2, 3 });
}
クラスがstd::get<I>(object)
とstd::tuple_size<T>::value
サポートしている限り、それは上記のprocess()
関数で拡張できます。関数自体は、引数の数に完全に依存しません。
整数からなるパラメータパックを作成する
std::integer_sequence
自体は、パラメータパックに変換できる整数のシーケンスを保持しています。その主な価値は、これらのシーケンスを作成する「ファクトリ」クラステンプレートを作成することです。
#include <iostream>
#include <initializer_list>
#include <utility>
template <typename T, T... I>
void print_sequence(std::integer_sequence<T, I...>) {
std::initializer_list<bool>{ bool(std::cout << I << ' ')... };
std::cout << '\n';
}
template <int Offset, typename T, T... I>
void print_offset_sequence(std::integer_sequence<T, I...>) {
print_sequence(std::integer_sequence<T, T(I + Offset)...>());
}
int main() {
// explicitly specify sequences:
print_sequence(std::integer_sequence<int, 1, 2, 3>());
print_sequence(std::integer_sequence<char, 'f', 'o', 'o'>());
// generate sequences:
print_sequence(std::make_index_sequence<10>());
print_sequence(std::make_integer_sequence<short, 10>());
print_offset_sequence<'A'>(std::make_integer_sequence<char, 26>());
}
print_sequence()
関数テンプレートは、整数シーケンスを展開するときにstd::initializer_list<bool>
して、評価の順序を保証し、未使用の[配列]変数を作成しません。
一連のインデックスを要素のコピーに変換する
カンマ式のインデックスのパラメータパックを値で展開すると、各インデックスの値のコピーが作成されます。悲しいことに、 gcc
とclang
はインデックスが効果がなく、警告をclang
と考えています( gcc
はインデックスをvoid
キャストしてサイレントにすることができvoid
):
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <string>
#include <utility>
template <typename T, std::size_t... I>
std::array<T, sizeof...(I)> make_array(T const& value, std::index_sequence<I...>) {
return std::array<T, sizeof...(I)>{ (I, value)... };
}
template <int N, typename T>
std::array<T, N> make_array(T const& value) {
return make_array(value, std::make_index_sequence<N>());
}
int main() {
auto array = make_array<20>(std::string("value"));
std::copy(array.begin(), array.end(),
std::ostream_iterator<std::string>(std::cout, " "));
std::cout << "\n";
}
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow