我想写类似的东西:
template<int i> void f() {}
for (constexpr int i : {1,2,3})
{
f<i>();
}
是否可以迭代constexpr?
谢谢
答案 0 :(得分:6)
正如您可能理解的那样,您不能这样做:
for (constexpr int i : {1,2,3})
{
f<i>();
}
因为,如果i
在循环中从1变为3,那么它是变量并且
不是编译时常量。变量不能是模板参数,
与f<i>
中一样:只有编译时常量可以是模板参数。
在C ++ 11及更高版本中,感谢variadic templates, 您可以有效地迭代编译时常量的任意序列 通过使用接受合适的任意序列的模板函数的编译时递归 模板参数。
如果您还不知道怎么做,那对您来说几乎没有任何意义。 这是一个C ++ 11示例,它可以表达您想要表达的内容:
#include <type_traits>
#include <iostream>
template<int i> void f()
{
std::cout << i << '\n';
}
// This overload is chosen when there is only 1 template argument.
template<int First, int ...Rest>
typename std::enable_if<sizeof...(Rest) == 0>::type
for_each_f()
{
f<First>();
}
// This overload is chosen when there is > 1 template argument.
template<int First, int ...Rest>
typename std::enable_if<sizeof...(Rest) != 0>::type
for_each_f()
{
f<First>();
for_each_f<Rest...>();
}
int main()
{
for_each_f<2,3,5,7,11>();
return 0;
}
除了可变参数模板,这种技术依赖于非常重要的C ++元编程
SFINAE的原则和std::enable_if
的原则,
这是标准C ++库为利用SFINAE提供的工具。
答案 1 :(得分:5)
不,你不能在编译时使用for循环进行迭代。 C ++中的for控制结构用于运行时控制流程。
但是,您可以使用其他编译时工具。例如,在C ++ 14中,您可以通过以下方式实现所需:
定义一个模板包装器类,它将调用您的函数。
template<int i> struct wrapper { void operator()() const { f<i>(); } };
使用std::index_sequence生成编译时索引。
template<template<int> class W, std::size_t... I> void caller_impl(std::index_sequence<I...>) { int t[] = { 0, ((void)W<I>()(), 1)... }; (void) t; } template<template<int> class W, std::size_t N, typename Indices = std::make_index_sequence<N>> void call_times() { caller_impl<W>(Indices()); }
然后拨打
int main() { call_times<wrapper, 42>(); }
如果C ++ 14不是一个选项,您可以查看here如何实现自己的std::index_sequence
。