C++
std :: integer_sequence
Sök…
Introduktion
std::integer_sequence<Type, Values...>
representerar en sekvens av värden av typ Type
där Type
är en av de inbyggda heltalstyperna. Dessa sekvenser används vid implementering av klass- eller funktionsmallar som drar nytta av positionsåtkomst. Standardbiblioteket innehåller också "fabrik" -typer som skapar stigande sekvenser med heltal bara från antalet element.
Vrid en std :: tupel till funktionsparametrar
En std::tuple<T...>
kan användas för att skicka flera värden runt. Till exempel kan den användas för att lagra en sekvens av parametrar i någon form av en kö. Vid bearbetning av en sådan tupel måste dess element förvandlas till funktionssamtalargument:
#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 });
}
Så länge en klass stöder std::get<I>(object)
och std::tuple_size<T>::value
kan den utvidgas med ovanstående process()
-funktion. Funktionen i sig är helt oberoende av antalet argument.
Skapa ett parameterpaket som består av heltal
std::integer_sequence
handlar om att hålla en sekvens av heltal som kan förvandlas till ett parameterpaket. Det primära värdet är möjligheten att skapa "fabrik" klassmallar som skapar dessa sekvenser:
#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()
använder en std::initializer_list<bool>
vid utökning av heltalssekvensen för att garantera utvärderingsordningen och inte skapa en oanvänd variabel [array].
Förvandla en sekvens av index till kopior av ett element
Att utöka parameterpaketet med index i ett kommauttryck med ett värde skapar en kopia av värdet för vart och ett av indexen. Tyvärr tror gcc
och clang
att indexet inte har någon effekt och varnar för det ( gcc
kan tystas genom att indexet blir 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";
}