C++ 这个for循环可以用预处理器完成吗?

C++ 这个for循环可以用预处理器完成吗?,c++,templates,arduino,c-preprocessor,fastled,C++,Templates,Arduino,C Preprocessor,Fastled,我的代码使用一个使用模板函数的库(FastLED): #define NUM_WIDGETS 4 Library.function<1>(); Library.function<2>(); Library.function<3>(); Library.function<4>(); #定义NUM\u小部件4 函数(); 函数(); 函数(); 函数(); 我不能将其放入普通的for循环中,因为模板参数需要在编译时可计算。我可以在预处理器中执行此

我的代码使用一个使用模板函数的库(FastLED):

#define NUM_WIDGETS 4

Library.function<1>();
Library.function<2>();
Library.function<3>();
Library.function<4>();
#定义NUM\u小部件4
函数();
函数();
函数();
函数();

我不能将其放入普通的for循环中,因为模板参数需要在编译时可计算。我可以在预处理器中执行此操作吗?还有其他建议吗?我希望能够在不复制粘贴这些行的情况下方便地更改NUM_小部件

您可以在以下帮助下使用模板执行此操作:

constexpr size\u t NUM\u WIDGETS=4;
模板
void foo(){

std::cout基于折叠表达式或递归模板的解决方案更为优越。但是,如果您需要预处理器解决方案,您可以查看编译器是否将包含深度作为预定义宏提供。例如,GCC提供了
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。然后,您可以使用递归包含生成模板函数调用

$ gcc -E r.cc | grep -v '^#' | sed '/^ *$/d'
int main()
{
   Library.function<1>();
   Library.function<2>();
   Library.function<3>();
   Library.function<4>();
}
$ cat r.cc
int main()
{
    #define NUM_WIDGETS 4
    #include "r.i"
}
$ cat r.i
#ifndef NUM_WIDGETS
# error "NUM_WIDGETS needs to be defined!"
#else
# if (__INCLUDE_LEVEL__) < ((NUM_WIDGETS) + 1)
   Library.function<__INCLUDE_LEVEL__>();
#  include __FILE__
# endif
#endif
$gcc-er.cc | grep-v'^#'| sed'/^*$/d'
int main()
{
函数();
函数();
函数();
函数();
}
$cat r.cc
int main()
{
#定义NUM_小部件4
#包括“r.i”
}
$cat r.i
#ifndefnum_小部件
#错误“需要定义NUM_小部件!”
#否则
#如果(uu包括_u级别)<((NUM_小部件)+1)
函数();
#包含文件__
#恩迪夫
#恩迪夫
此技术仅限于编译器的嵌套包含限制。

中的模板解决方案无疑是一条可行之路

但是,事实上,您也可以使用预处理器进行处理:

#include <iostream>
#include <boost/preprocessor/repetition/repeat.hpp>

template <int N> void function() { std::cout << N << "\n"; }

#define NUM_WIDGETS 4

int main()
{
#define CALL_FUNC(z,n,d) function<n+1>();
    BOOST_PP_REPEAT(NUM_WIDGETS, CALL_FUNC, ~)
#undef CALL_FUNC
}
#包括
#包括

模板void function(){std::cout正如我在前面的评论中提到的,使用模板比使用预处理器更容易做到这一点

首先定义一个模板

 template<unsigned n> void invoke() {Library.function<n>();  invoke<n-1>();};
template void invoke(){Library.function();invoke();};
然后专门研究一个不起作用的结束条件

 template<> void invoke<0U>() {};
模板void invoke(){};
叫它

 int main()
 {
      invoke<NUM_WIDGETS>();
 }
intmain()
{
调用();
}
这将按与指定相反的顺序调用函数。可以通过将模板函数更改为

 template<unsigned n> void invoke() {Library.function<NUM_WIDGETS + 1 - n>(); invoke<n-1>();};
template void invoke(){Library.function();invoke();};
并保持相同的专业化以结束递归


当然,如果你需要这样做(无论是使用预处理器还是模板),这暗示着一个坏的设计,你应该问为什么
Library.function()
首先是一个模板。

看看Not preprocessor.Recursive template。
template void invoke(){Library.function();invoke(i-1);};
具有结束递归的专门化
模板void invoke(){};
 int main()
 {
      invoke<NUM_WIDGETS>();
 }
 template<unsigned n> void invoke() {Library.function<NUM_WIDGETS + 1 - n>(); invoke<n-1>();};