C++
std :: integer_sequence
Szukaj…
Wprowadzenie
std::integer_sequence<Type, Values...>
reprezentuje sekwencję wartości typu Type
gdzie Type
jest jednym z wbudowanych typów całkowitych. Sekwencje te są używane przy wdrażaniu szablonów klas lub funkcji, które korzystają z dostępu pozycyjnego. Biblioteka standardowa zawiera również typy „fabryczne”, które tworzą rosnące sekwencje wartości całkowitych tylko na podstawie liczby elementów.
Włącz std :: krotkę w parametry funkcji
std::tuple<T...>
może służyć do przekazywania wielu wartości. Na przykład można go użyć do przechowywania sekwencji parametrów w jakiejś formie kolejki. Podczas przetwarzania takiej krotki należy przekształcić jej elementy w argumenty wywołania funkcji:
#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 });
}
Tak długo, jak klasa obsługuje wartości std::get<I>(object)
i std::tuple_size<T>::value
, można ją rozszerzyć o powyższą funkcję process()
. Sama funkcja jest całkowicie niezależna od liczby argumentów.
Utwórz pakiet parametrów składający się z liczb całkowitych
Sam parametr std::integer_sequence
polega na utrzymywaniu sekwencji liczb całkowitych, które można przekształcić w pakiet parametrów. Jego podstawową wartością jest możliwość tworzenia szablonów klas „fabrycznych”, tworząc następujące sekwencje:
#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>());
}
Szablon funkcji print_sequence()
korzysta ze std::initializer_list<bool>
podczas rozwijania sekwencji liczb całkowitych, aby zagwarantować kolejność obliczeń i nie tworzyć nieużywanej zmiennej [tablica].
Zamień sekwencję indeksów w kopie elementu
Rozszerzenie pakietu parametrów indeksów w wyrażeniu przecinkowym o wartość tworzy kopię wartości dla każdego z indeksów. Niestety, gcc
i clang
sądzą, że indeks nie ma żadnego efektu i ostrzegają przed nim ( gcc
można wyciszyć, rzutując indeks na 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";
}