4 Eylül 2019 Çarşamba

std::index_sequence

Giriş
std::integer_sequence ile kardeştir.

Parametre Olarak Geçmek
Örnek
Template koduna şöyle yazarız
template<std::size_t... Is>
void foo(std::index_sequence<Is...>) {
  ...
}
Örnek
Elimizde şöyle bir kod olsun.
namespace detail
{
  template <typename T, std::size_t ... Is>
  constexpr std::array<T, sizeof...(Is)>
  create_array(T value, std::index_sequence<Is...>)
  {
    // cast Is to void to remove the warning: unused value
    return {{(static_cast<void>(Is), value)...}};
  }
}

template <std::size_t N, typename T>
constexpr std::array<T, N> create_array(const T& value)
{
  return detail::create_array(value, std::make_index_sequence<N>());
}
Şöyle yaparız. Böylece 10'luk bir diziyi hep 7 değeri ile ilklendiririz.
auto a = create_array<10 /*, int*/>(7); // auto is std::array<int, 10>

Örnek
Eğer index 0 olursa aslında boş bir dizidir. Bu ikisini ayırt etmek için şöyle yaparız.
auto func1(std::index_sequence<>)
{
  return func2();
}

template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
  auto var = get_tuple();
  return func2(std::get<I>(var)...);
}
Şöyle yaparsak ilk metoda girer.
auto a = func1(std::make_index_sequence<0>());
Index'in Üst Sınırı
Örnek
Şöyle yaparız.
template <std::size_t... I>
auto func1(std::index_sequence<I...>)
{
  if constexpr (sizeof ...(I) == 0) {
    return func2();
  } else {
    auto var = get_tuple();
    return func2(std::get<I>(var)...);
  }
}
Şöyle yaparsak ilk koşula girer.
auto a = func1(std::make_index_sequence<0>());
Her Index'e Erişmek
std::get<Is>(..) şeklinde yaparız
template<typename F, std::size_t... Is, class Tup>
void foo(F && f, std::index_sequence<Is...>, Tup && tup) {
  std::forward<F>(f)( std::get<Is>(std::move(tup))... );
}
Örnek
Şöyle yaparız.
template <std::size_t... Is>
constexpr auto make_array_from_sequence_impl(std::index_sequence<Is...>)
{
    return std::array<std::size_t, sizeof...(Is)>{Is...};
}

template <typename Seq>
constexpr auto make_array_from_sequence(Seq)
{
    return make_array_from_sequence_impl(Seq{});
}
Çağırmak için şöyle yaparız.
int main()
{
  constexpr auto arr = make_array_from_sequence(make_sequence<6>());
  static_assert(arr[0] == 0);
  static_assert(arr[1] == 1);
  static_assert(arr[2] == 2);
  static_assert(arr[3] == 4);
  static_assert(arr[4] == 5);
  static_assert(arr[5] == 7);
}

Hiç yorum yok:

Yorum Gönder