Finding the position of the first occurrence of a value in std :: integer_sequence

I want to find the position of the first occurrence of a value in std::integer_sequence.

  • Is there an algorithm in the standard library for this task?
  • If not, what would be a good way?

-

Below is my attempt. It works, but I do not find it very elegant; also, it cannot produce a pure error ("value not found") when this value is absent (code is commented out due to compilation). (Also, the need to specify an integer type in Find_in_integer_sequenceseems redundant, but I believe there is no way around it.)

The code is only for your entertainment, it should not be the starting point for the proposed solution.

# include <iostream>
# include <utility>
# include <type_traits>

namespace detail
{
  template < int Idx, typename T, T Match, T ...Values >
  struct Find;

  template < int Idx, bool B, typename T, T Match, T ...Values >
  struct Find_impl;

  template < int Idx, typename T, T Match, T ...Values >
  struct Find_impl<Idx, true, T, Match, Values...>
  {
    static const int value = Idx;
  };

  template < int Idx, typename T, T Match, T Value, T ...Other_values >
  struct Find_impl<Idx, false, T, Match, Value, Other_values...>
    : public Find<(Idx + 1), T, Match, Other_values...>
  {
  };

  template < int Idx, typename T, T Match, T Value, T ...Other_values >
  struct Find<Idx, T, Match, Value, Other_values...>
    : public Find_impl<Idx, (Match == Value), T, Match, Value, Other_values...>
  {
  };

  //template < int Idx, typename T, T Match >
  //struct Find<Idx, T, Match>
  //{
  //  static_assert(false, "value not found");
  //};
}

template < typename T, T Match, T ...Values >
struct Find
  : public detail::Find<0, T, Match, Values...>
{
};

template < typename T, T Match, typename TIS >
struct Find_in_integer_sequence;

template < typename T, T Match, T ...Values>
struct Find_in_integer_sequence<T, Match, std::integer_sequence<T, Values...>>
  : public Find<T, Match, Values...>
{
};

int main()
{
  using i1 = std::integer_sequence<int, 2, 3, 3, 2, 3, 2, 0>;
  auto k = Find_in_integer_sequence<int, 0, i1>::value;
  std::cout << k << std::endl; # prints "6"
  return 0;
}
+4
source share
2

++ 14 constexpr :

template<  class U, class T, T...ts >
constexpr std::size_t find( U t, std::integer_sequence<T, ts...> s )
{
    T s_arr[] = {ts...};
    for (std::size_t i = 0; i != sizeof...(ts); ++i) {
        if (s_arr[i] == t) return i;
    }
    return sizeof...(ts);
}

. .


, . , , , constexpr. ++ 11 :

template<std::size_t N>using index=std::integral_constant<std::size_t,N>;

template<class T, T...t0s, T...t1s>
constexpr std::integer_sequence<T, t0s..., t1s... >
join( std::integer_sequence<T,t0s...>, std::integer_sequence<T,t1s...>){
  return {};
}
template<class T, T...ts>
constexpr auto split( index<0>, std::integer_sequence<T,ts...> s ){
  return std::make_pair( std::integer_sequence<T>{}, s );
}
template<class T, T t0,  T...ts>
constexpr auto split( index<1>, std::integer_sequence<T, t0, ts...> s ){
  return std::make_pair( std::integer_sequence<T, t0>{}, std::integer_sequence<T,ts...>{} );
}

template<std::size_t N, class T, T...ts>
constexpr auto split( index<N>, std::integer_sequence<T, ts...> s ){
  auto a = split(index<N/2>{}, s );
  auto b = split(index<(N+1)/2>{}, a.second );
  return std::make_pair( join(a.first, b.first), b.second );
}
template< class T, T t0, T t1 >
constexpr index<1> find( std::integral_constant<T,t0>, std::integer_sequence<T, t1> )
{ return {}; }

template< class T, T t0, T...ts >
constexpr index<0> find( std::integral_constant<T,t0>, std::integer_sequence<T, t0, ts...> )
{ return {}; }
template< class T, T t0, T...ts >
constexpr index<1> find( std::integral_constant<T,t0>, std::integer_sequence<T> )
{ return {}; }
template< class T, T t0, T...ts >
constexpr auto find( std::integral_constant<T,t0> t, std::integer_sequence<T, ts...> s )
{
  index<sizeof...(ts)/2> half;
  auto halves = split( half, s );
  auto front = find( t, halves.first );
  auto back = find( t, halves.second );
  return index<(front < half)?front:(back+half)>{};
}

, .

.

+3

constexpr:

#include <iostream>
#include <utility>
#include <type_traits>

template<class T>
constexpr int find_(std::integer_sequence<T>, T, int Idx) {
    return Idx;
}

template<class T, T Head, T... Tail>
constexpr int find_(std::integer_sequence<T, Head, Tail...>, T Value, int Idx) {
    return Value == Head ? Idx : find_(std::integer_sequence<T, Tail...>{}, Value, Idx + 1);
}

template<class S, class T>
constexpr auto findT(S s, T Value) {
    return find_(s, Value, 0);
}

int main() {
    using i1 = std::integer_sequence<int, 2, 3, 3, 2, 3, 2, 0>;
    constexpr auto k = findT(i1{}, 0);
    static_assert(k == 6, "Compile time constant check.");
    std::cout << k << std::endl; // prints "6"
}
+1

Source: https://habr.com/ru/post/1681567/


All Articles