C++ 在编译时为稀疏数组索引自动生成switch语句

C++ 在编译时为稀疏数组索引自动生成switch语句,c++,templates,c++17,sparse-matrix,index-sequence,C++,Templates,C++17,Sparse Matrix,Index Sequence,有没有办法生成编译时开关语句来匹配索引?例如,如果我有一个序列1,5,8,并且我想将它与0,1,2匹配,那么编译器是否可以在编译时生成一个函数,当给定1,5,8时,该函数分别返回0,1,2。为了更好地说明我想要什么,我准备了以下稀疏数组结构: #包括 #包括 模板 大小\u得不到\u idx() { 静态断言(Idx==I | | sizeof…(Is)>0,“未找到索引”); 如果constexpr(Idx==I)返回深度; 否则返回get_idx(); } 模板 结构稀疏数组 { const

有没有办法生成编译时开关语句来匹配索引?例如,如果我有一个序列
1,5,8
,并且我想将它与
0,1,2
匹配,那么编译器是否可以在编译时生成一个函数,当给定1,5,8时,该函数分别返回0,1,2。为了更好地说明我想要什么,我准备了以下稀疏数组结构:

#包括
#包括
模板
大小\u得不到\u idx()
{
静态断言(Idx==I | | sizeof…(Is)>0,“未找到索引”);
如果constexpr(Idx==I)返回深度;
否则返回get_idx();
}
模板
结构稀疏数组
{
constexpr静态大小N=sizeof…(Is);
constexpr static size_t size(){return N;}
te[N];
constexpr稀疏数组():e{}{}
模板
constexpr稀疏数组(const type_pack&…pack):e{pack…}
{
static_assert(sizeof…(type_pack)=size(),“参数计数必须为马赫数组大小”);
}
模板
constexpr size_t idx()
{
返回get_idx();
}
尺寸idx(常数尺寸i)
{
//如何做到这一点?
返回idx();
}
施工测试和测试(尺寸为idx)
{
返回e[idx];
}
};
模板
自动生成密集数组(标准::索引序列&&seq)
{
返回稀疏_数组{};
}
模板
使用密集数组=decltype(使密集数组(std::declval());
尺寸试验()
{
密集阵列a;
稀疏阵列b;
返回b.idx();
}
我还希望能够传入运行时变量,这些变量将通过带有索引的开关,并返回相应的索引。解决这个问题的唯一方法是生成一个
序列数组,然后使用if语句生成一个for循环,以返回正确的索引。另一个选项是,使用映射(但这也不是编译时)。稀疏数组通常非常小,我希望能够在编译时完成大部分工作。

类似这样的事情

static constexpr size_t idx(size_t i)
{
    size_t j = 0;
    if(!(... || (j++, i == Is))) {
        throw "Index out of range!";
    }
    return j-1;
}
读起来可能有点棘手,但如果我理解正确的话,你应该做你想做的事情。实例化后,这基本上相当于一系列的
if-else
通过
is
中的索引从左向右移动

通过将折叠表达式的主体分离为lambda,可以使其更具可读性。您还应该将
throw
表达式替换为对您来说合理的表达式

使用
constexpr
限定符,也可以将其用于模板版本:

template<size_t I, auto s = idx(I)>
static constexpr size_t idx() {
    return s;
}
同样,最好替换循环中的早期退出

如果数组更大,则不仅可以使用带循环的声明数组,而且可以在该数组上正确地实现二进制搜索


可以使用标准算法,如
std::any_
std::find
std::binary_search
代替手动搜索实现。然而,这些算法只有在C++20中才是
constepr
,因此这将限制这里的使用。

似乎正是我想要的。我有一个类似的版本,但无法使其工作,因为我的一些函数需要编译时表达式。这看起来不错,但也不难理解(至少对我来说)。@lightxbulb我添加了更多信息,因为除了非常少量的索引外,你真的应该使用不同的方法。我意识到对于较大的数组,可以使用map和unordered_map,但它们都是运行时的。我假设在编译时也可以实现完美的哈希,但这远远超出了我的需要和目标。我的阵列通常不会超过10个项目,这也是我使用静态阵列进行数据存储的原因。
static constexpr size_t idx(size_t i)
{
    static constexpr std::array ind{Is...};
    size_t j = 0;
    for(; j < ind.size() && i != ind[j]; j++);
    if(j == ind.size())
        throw "Index out of range!";
    return j;
}