You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++17中将循环索引用作constexpr/模板参数的实现方案

C++17编译时循环调用模板函数问题解决

语言与标准:C++17

需求描述

我创建了一个由constexpr构造的全局数组(例如int List[someconstant]),其元素可作为模板参数或传入其他constexpr函数、变量。现有如下for循环:

for(int i = 0; i < __MYCONST__ ; i++){
    int j = List[i];
    function<j>(/*循环外声明的部分数据*/);
}

其中__MYCONST__是编译时常量(constexpr全局变量),我已成功将其作为模板参数在代码其他位置使用。我希望写成constexpr int j = List[i];或直接function<List[i]>();,但因i被视为变量而失败。i在循环内未被修改,且循环边界为编译时已知,因此我认为存在实现constexpr int j的方法。

问题

  1. 可替换当前for循环的何种构造能让我声明constexpr的j?
  2. 是否存在更简便的方式,调用模板参数依赖于i(通过constexpr数组)的模板函数,无需声明constexpr的j并将其作为模板参数传递?

备注:无法将List[i]作为函数参数传递,必须用作模板参数。

已尝试实现

我已实现一个constexpr_loop函数:

template <int i, int N, typename FunctorType> 
struct  basic_recursive{
    basic_recursive(FunctorType fun){
        fun(i);
        basic_recursive<i+1,N,FunctorType> a(fun);
    };
};
template <int N, typename FunctorType> 
struct basic_recursive<N,N,FunctorType>{
    basic_recursive(FunctorType fun){};
};

template<int i, int N, typename FunctorType>
void constexpr_for(FunctorType fun){
    basic_recursive<i,N,FunctorType> a(fun);
}

调用方式为constexpr_for([&](int i) {循环体}),该实现通过模板函数处理参数推导、模板结构体偏特化处理终止逻辑,二者配合完成递归循环。

我希望将其适配为支持带非类型模板参数的FunctorType,即循环索引作为模板参数,在构造函数中调用fun<i>()而非fun(i)。尝试使用C++20模板lambda但无法实现模板参数推导。

最小可复现示例(MWE)

我尝试实现了以下代码:

template <int i, int N, typename FunctorType> 
struct  basic_recursive2{
  basic_recursive2(FunctorType fun){ 
      fun();
      basic_recursive2<i+1,N,FunctorType> a(fun);
  };
};
template <int N, typename FunctorType> 
struct basic_recursive2<N,N,FunctorType>{
  basic_recursive2(FunctorType fun){};
};

template<int i, int N, template<int> typename FunctorType>
void constexpr_for2(FunctorType<i> fun){
  basic_recursive2<i,N,FunctorType<i>> a(fun);
}

主函数中调用:

constexpr_for2<1,3>([&]<int i>{printf("print in temp lambda %d \n",i);});

但编译报错:

file.cxx: error: no matching function for call to 'constexpr_for2'
  constexpr_for2<1,3>([&]<int i>{printf("print in temp lambda %d \n",i);});
  ^~~~~~~~~~~~~~~~~~~
file.cxx: note: candidate template ignored: could not match 'FunctorType<1>' against '(lambda at file.cxx)'
void constexpr_for2(FunctorType<i> fun){
     ^
file.cxx: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'FunctorType'
void constexpr_for2(FunctorType<i> fun){
     ^

解决方案

@user17732522提出以下解决方案:

[&]<int... j>(std::integer_sequence<int, j...>{
 (function<List[j]>(/*循环外声明的部分数据*/), ...); 
}(std::make_integer_sequence<int, __MYCONST__>{});

该方案通过模板lambda结合std::make_integer_sequence生成编译时整数序列,利用参数包展开实现循环,将每个序列元素作为模板参数调用function<List[j]>。

我将其适配为支持多语句循环体的版本,通过嵌套模板lambda实现:

[&]<int... j>(std::integer_sequence<int, j...>{
 ( [&]<int i>{
  依赖i的指令1;
  依赖i的指令2;...
}.template operator()<j>(),...);
}(std::make_integer_sequence<int, __MYCONST__>{});

该实现带来显著性能提升,调用的模板化函数性能提升2.5至4倍。


内容的提问来源于stack exchange,提问作者Sardine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:14:56