【问题标题】:How to fill const std::array<size_t, N> with values based on function如何用基于函数的值填充 const std::array<size_t, N>
【发布时间】:2016-03-12 16:01:57
【问题描述】:

如何创建包含以下值 f(0)、f(1)、...、f(N-1) 的 const std::array,其中 f 是任意函数:static constexpr size_t f(int index)? 当我确切地知道 N 时,我显然可以写出

const std::array<size_t, 5> a = {f(0), f(1), f(2), f(3), f(4)}

【问题讨论】:

  • 你有 C++14 支持吗?
  • 向我们展示您已经尝试过的内容,而不是期望 SO 从头开始​​为您编写代码
  • @Brian 是的,甚至 c++17。
  • @hellofunk 我用谷歌搜索并没有发现任何有用的东西。我看不出显示我的代码不起作用的意义。
  • @BenonAdamczyk 显示您的代码不起作用的要点实际上是 SO 的全部要点。如果您的代码有效,您将不会发布问题。然后,您将了解更多关于您的编码出错的地方,其他人可以帮助您了解您的思维过程。问一个开放式的问题,你希望其他人完全为你编写代码,这通常是不受欢迎的。

标签: c++ c++11 c++14


【解决方案1】:

创建需要任意复杂初始化的常量的一般技术是简单地编写一个返回所需值的函数,然后在常量的初始化程序中调用它。例如:

template <typename T, size_t N>
array<T, N> init_from_f() {
    array<T, N> a;
    for (size_t i = 0; i < N; ++i)
        a[i] = f(i);
    return a;
}

const auto const_array = init_from_f<sometype, 42>();

【讨论】:

  • 一个有用的概括是使init_from_f也模板化f,并作为init_from_fn&lt;sometype, 42, f&gt;调用。这将使其更通用,适用于任意函数对象甚至 lambda,而不会牺牲可读性。
【解决方案2】:

它可能需要打磨,但我就是这么想的:

template <std::size_t... ns, typename Fn>
auto fill_helper(std::integer_sequence<std::size_t, ns...>, Fn&& fn) -> std::array<decltype(fn(std::size_t())), sizeof...(ns)>  {
    return {{fn(ns)...}};
} 

template <std::size_t N, typename Fn>
auto fill(Fn&& fn) {
    using seq = std::make_integer_sequence<std::size_t, N>;
    return fill_helper(seq(), std::forward<Fn>(fn));    
}

int main() {

    auto plus5 = [](std::size_t index) {
        return index + 5;
    };

    auto const as = fill<5>(plus5);
    for (auto&& a: as)
        std::cout << a;

}

优点是您使用正确的值初始化数组,而不是先初始化然后分配。

【讨论】:

    【解决方案3】:

    如果您想在不创建外部函数的情况下对其进行 const 初始化,也可以这样做:

    void SomeFunction() {
    
        const auto my_array = [](){
            auto a = array<SomeType, N>();
            for (size_t i = 0; i < a.size(); ++i)
                a[i] = f(i);
            return a;
        }(); // <-- Note that the lambda executes right away
    
        DoSomeStuff(my_array);
    }
    

    【讨论】:

      【解决方案4】:

      使用 lambda 和 std::generate:

      #include<array>
      #include<algorithm> // generate
      #include<cassert>
      #include<iostream>
      
      int f(int i){return i*i;}
      
      int main(){
          const std::array<int, 5> a = []{
              std::array<int, 5> a;
              int n = 0;
              std::generate(a.begin(), a.end(), [&n]{ return f(n++); });
              return a;
          }();
          assert( a[4] == 16 );
      }
      

      http://coliru.stacked-crooked.com/a/60e2ec92e648519d

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-06
        • 2019-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多