查找 std::integer_sequence 中首次出现的值的位置
Finding the position of the first occurrence of a value in an std::integer_sequence
我想找到std::integer_sequence
中第一次出现的值的位置。
- 标准库中是否有用于此任务的算法?
- 如果没有,那将是什么好方法呢?
--
以下是我的尝试。它有效,但我不觉得它很优雅;此外,当值不存在时,它不会产生干净的错误("找不到值"((由于编译而注释掉的代码(。(另外,必须在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++14constexpr
很棒:
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)>{};
}
这解决了对数递归深度的问题,允许搜索整数的百万条目列表。
两者的活生生的例子。
另一种方法是使用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"
}
相关文章:
- 将值指定给向量(2D)的向量中的某个位置
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 使用Unreal C++获取VR耳机的世界位置/方向
- 写入位置0x0000000C时发生访问冲突
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- GL_SHADERSTORAGE_BUFFER位置是否与其他着色器位置冲突
- 如何使用cudaMallocManaged在指针位置初始化对象?(C++)
- 无法获取webot::PositionSensor对象中位置传感器的值
- 非常量变量只读位置的赋值
- 如何定义更改car类中car位置的方法
- 使用迭代器时如何访问对象在向量中的位置?
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 求最大元素位置的分治算法
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 为什么我的点没有在 OpenGL 中绘制鼠标所在的位置?
- 如何将元素添加到向量的字符串位置
- 如何选择在 csv 文件中输出的位置
- 无法打开 fstream C++文件,即使它与 .cpp 位于同一位置
- 如何在特定位置追加 json 文件
- 0xC0000005:读取Integer的位置时发生访问冲突