【问题标题】:Possible to initialize const std::array with repeated function call? [duplicate]可以通过重复的函数调用来初始化 const std::array 吗? [复制]
【发布时间】:2017-07-12 05:57:12
【问题描述】:

这样可以吗

int foo(){
  static int i=0;
  ret = i++;
  return ret;
}
const std::array<int,3> arr = {{foo(),foo(),foo()}};

在(模板?)函数或指定“调用 foo 以初始化每个成员”的方式中?即

const std::array<int,3> arr = fill_with_foo<3,foo>();

对于上下文,arr 是队列中的一个缓冲区,将从中读取 N 个元素(在编译时已知)。目前我正在使用代码生成来创建长表单,并且我有一个函数,它只是分配一个普通数组,用一个 for 循环填充它并返回数组,但我想知道是否可以使用缓冲区数组 const。

//编辑:不像链接的“重复”,我需要

int foo();

在编译时是不确定的,即我认为 constexpr 是不可能的(正如我所说,它需要从运行时填充的队列中读取)。我主要对删除无用的副本感兴趣

【问题讨论】:

  • 你试过把它变成 constexpr 吗?
  • @Bob__ 我认为在运行时填充的队列不起作用?

标签: c++ arrays c++11


【解决方案1】:

C++ 14 开始,人们可能会使用 std::index_sequnce(或为旧版本手动实现它):

namespace detail
{

template<typename T, std::size_t N, typename F, std::size_t... I>
constexpr std::array<T, N> construct(F&& func, std::index_sequence<I...>)
{
    return { { (static_cast<void>(I), func())... } };
}

template<typename T, std::size_t N, typename F>
constexpr std::array<T, N> construct(F&& func)
{
    return construct<T, N>(std::forward<F>(func), std::make_index_sequence<N>());
}

}

然后你可以如下应用它:

const auto array = detail::construct<T, 3>(foo);

FULL CODE

另请注意,constexpr 甚至可以在编译时构造 std::array

EXAMPLE

【讨论】:

  • 你确定调用非 constexpr 函数 func 不会干扰被调用函数的 constexpr-ness 吗?在c ++ 11中还有index_sequence的实现,值得一提的是标签。
  • @W.F.当然,调用非 constexpr 函数也会使这个解决方案成为非 constexpr,这就是为什么我写了 "even at compile time",而不是 "always at compile time" : )
  • here 你去 :)
  • @W.F.是的,我想我知道今晚我会读什么:)
  • @IgorK constexpr 的基本属性是它意味着代码可以constexpr 上下文中使用;这并不意味着它必须是。标记为constexpr 的代码也可以在其他情况下使用。埃德加和 W.F.上面已经讨论过了。
【解决方案2】:

考虑让函数返回std::array。大多数编译器中的 NRVO 都会省略副本。

#include <array>
#include <iostream>

template <typename T, std::size_t N, typename F>
std::array<T, N> fill_array(F const &fn)
{
    std::array<T, N> arr;

    for (auto i = std::begin(arr); i != std::end(arr); ++i) {
        *i = fn();
    }

    return arr;
}

int foo(){
  static int i=0;
  return i++;
}

int main() {
    auto const arr = fill_array<int, 3>(foo);
    for (auto const &i : arr) {
        std::cout << i << '\n';
    }
    return 0;
}

Demo

【讨论】:

  • 是的,我认为 c++17 甚至可以保证复制省略
  • @W.F.仅适用于 RVO,不适用于 NRVO。
  • 这就是我的想法,我只是不确定复制省略
猜你喜欢
  • 2018-01-13
  • 1970-01-01
  • 2020-09-17
  • 2015-09-04
  • 2011-03-19
  • 2020-10-20
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多