用constexpr迭代

Vio*_*tte 8 c++ c++11

我想写这样的东西:

template<int i> void f() {}

for (constexpr int i : {1,2,3})
{
    f<i>();
}
Run Code Online (Sandbox Code Playgroud)

是否可以迭代constexpr?

谢谢

Mik*_*han 6

你可能理解,你不能这样做:

for (constexpr int i : {1,2,3})
{
    f<i>();
}
Run Code Online (Sandbox Code Playgroud)

因为,如果i在循环中从1到3变化,那么它是变量而不是编译时常量.并且变量不能是模板参数,例如f<i>:只有编译时常量可以是模板参数.

在C++ 11及更高版本中,由于可变参数模板,您可以通过使用接受合适的任意模板参数序列的模板函数的编译时递归来有效地迭代编译时常量的任意序列.

如果您还不知道如何做,那对您来说几乎没有任何意义.这是一个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;
}
Run Code Online (Sandbox Code Playgroud)

现场观看

除了可变参数模板之外,这种技术还依赖于SFINAE非常重要的C++元编程原理,以及std::enable_if标准C++库为利用SFINAE提供的工具.

101010的答案演示了C++ 14中提供的更复杂和强大的解决方案风格(如果您编写一些支持样板,则很容易在C++ 11中实现).


101*_*010 5

不,你不能在编译时使用for循环迭代.C++中的for控制结构用于运行时控制流程.

但是,您可以使用其他编译时功能.例如,在C++ 14中,您可以通过以下方式实现所需:

  1. 定义一个模板包装类,它将调用您的函数.

    template<int i>
    struct wrapper {
      void operator()() const { f<i>(); }
    };
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用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());
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 然后打电话给

    int main() {
      call_times<wrapper, 42>();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    现场演示

如果C++ 14是不是一种选择,你可以看看这里的你如何能实现std::index_sequence你的自我.