C++
std :: integer_sequence
Ricerca…
introduzione
std::integer_sequence<Type, Values...>
rappresenta una sequenza di valori di tipo Type
cui Type
è uno dei tipi interi incorporati. Queste sequenze vengono utilizzate quando si implementano modelli di classi o funzioni che traggono vantaggio dall'accesso posizionale. La libreria standard contiene anche i tipi "factory" che creano sequenze ascendenti di valori interi solo dal numero di elementi.
Trasforma una tupla std :: in parametri di funzione
Una std::tuple<T...>
può essere utilizzata per passare più valori in giro. Ad esempio, potrebbe essere usato per memorizzare una sequenza di parametri in qualche forma di coda. Quando si elabora una tale tupla, i suoi elementi devono essere convertiti in argomenti di chiamata di funzione:
#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 });
}
Finché una classe supporta std::get<I>(object)
e std::tuple_size<T>::value
può essere espanso con la funzione process()
sopra. La funzione stessa è completamente indipendente dal numero di argomenti.
Creare un pacchetto di parametri costituito da numeri interi
std::integer_sequence
riguarda lo svolgimento di una sequenza di numeri interi che possono essere trasformati in un pacchetto di parametri. Il suo valore principale è la possibilità di creare modelli di classe "factory" creando queste sequenze:
#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>());
}
Il modello di funzione print_sequence()
usa una print_sequence()
std::initializer_list<bool>
quando si espande la sequenza intera per garantire l'ordine di valutazione e non creare una variabile [array] inutilizzata.
Trasforma una sequenza di indici in copie di un elemento
L'espansione del pacchetto di parametri degli indici in un'espressione di virgola con un valore crea una copia del valore per ciascuno degli indici. Purtroppo, gcc
e clang
pensano che l'indice non abbia alcun effetto e lo mettano in guardia ( gcc
può essere messo a tacere gettando l'indice a 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";
}