C++
std :: integer_sequence
Recherche…
Introduction
std::integer_sequence<Type, Values...>
représente une séquence de valeurs de type Type
où Type
est l'un des types entiers intégrés. Ces séquences sont utilisées lors de l'implémentation de modèles de classe ou de fonction bénéficiant d'un accès positionnel. La bibliothèque standard contient également des types "factory" qui créent des séquences ascendantes de valeurs entières à partir du nombre d'éléments.
Tournez un std :: tuple en paramètres de fonction
Un std::tuple<T...>
peut être utilisé pour transmettre plusieurs valeurs. Par exemple, il pourrait être utilisé pour stocker une séquence de paramètres dans une forme de file d'attente. Lors du traitement d'un tel tuple, ses éléments doivent être transformés en arguments d'appel de fonction:
#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 });
}
Tant qu'une classe supporte std::get<I>(object)
et std::tuple_size<T>::value
elle peut être développée avec la fonction process()
ci-dessus. La fonction elle-même est entièrement indépendante du nombre d'arguments.
Créer un pack de paramètres composé d'entiers
std::integer_sequence
lui-même consiste à maintenir une séquence d'entiers pouvant être transformée en un paquet de paramètres. Sa principale valeur est la possibilité de créer des modèles de classe "factory" en créant ces séquences:
#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>());
}
Le modèle de fonction print_sequence()
utilise un std::initializer_list<bool>
lors de l'extension de la séquence entière pour garantir l'ordre d'évaluation et ne pas créer de variable [array] inutilisée.
Transforme une séquence d'indices en copies d'un élément
L'extension du paquet de paramètres d'index dans une expression virgule avec une valeur crée une copie de la valeur pour chacun des index. Malheureusement, gcc
et clang
pense que l'indice n'a pas d' effet et mettre en garde à ce sujet ( gcc
peut être réduit au silence par coulée l'indice d' 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";
}