gpt4 book ai didi

c++ - 查找值在 std::integer_sequence 中第一次出现的位置

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:50:45 24 4
gpt4 key购买 nike

我想找到一个值在 std::integer_sequence 中第一次出现的位置。

  1. 标准库中是否有用于此任务的算法?
  2. 如果没有,什么是做这件事的好方法?

--

下面是我的尝试。它有效,但我觉得它不是很优雅;当值不存在时(代码因编译而被注释掉),它也无法产生干净的错误(“未找到值”)。 (此外,必须在 Find_in_integer_sequence 中指定整数类型感觉有些多余,但我认为没有办法解决它。)

代码仅供您娱乐,不应作为建议解决方案的起点。

# 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;
}

最佳答案

C++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 函数中的平面数组中。可以修改此版本以在 C++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)>{};
}

这解决了对数递归深度的问题,允许搜索包含百万个条目的整数列表。

Live example of both .

关于c++ - 查找值在 std::integer_sequence 中第一次出现的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45132208/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com