我如何构造一个填充有一些统一值的std :: array?

问题描述

可以构造具有特定值的

std::array(在编译时使用较新的C ++版本),例如

std::array a{1,4,9};

但是-它没有构造函数,也没有标准的库,称为构造函数的惯用语,它只取一个值并将其复制。即我们没有:

std::array<int,3> a{11};
// a == std::array<int,3>{11,11,11};

因此,我们如何构造仅给出要重复的值的数组?

编辑:我正在寻找一种解决方案,该解决方案甚至适用于无法默认构造的元素类型;因此,我不需要的是通过默认构造数组然后填充它的解决方案-尽管事实上这对于int来说是有效的(如示例中所示)。

解决方法

我们可以编写一个合适的named constructor idiom来实现这一目标

该实现有些笨拙,但是,由于我们需要使用"indices trick",在C ++ 11中需要大量样板,因此我们假设C ++ 14:

namespace detail {

template<size_t,class T>
constexpr T&& identity(T&& x) { return std::forward<T>(x); }

template<class T,size_t... Indices>
constexpr auto array_repeat_impl(T&& x,std::index_sequence<Indices...>)
{
    return std::experimental::make_array(identity<Indices>(x)...);
}

} // end detail

template<size_t N,class T>
constexpr auto array_repeat(T&& x)
{
    return detail::array_repeat_impl(std::forward<T>(x),std::make_index_sequence<N>());
}

请参见GodBolt上的内容。

如果可以编译C ++ 20代码,则可以删除对make_array的依赖关系并编写:

namespace detail {

template<size_t,std::index_sequence<Indices...>)
{
    return std::array{identity<Indices>(x)...};
}

} // end detail

template<size_t N,std::make_index_sequence<N>());
}

GodBolt

注意:

  • 此解决方案有点类似于Jared Hoberock的tuple utilities for C++11tuple_repeat
  • 感谢@Caleth和@ L.F。在array_repeat_impl中指出不适当的转发。
,

使用C ++ 20,当类型是默认可构造且可复制的类型时,可以使用now-constexpr fill函数(live example)直接为此提供帮助:

#include <array>
#include <concepts>
#include <cstddef>

template<std::size_t N,std::semiregular T>
constexpr auto array_repeat(const T& value) -> std::array<T,N> {
    std::array<T,N> ret;
    ret.fill(value);
    return ret;
}

int main() {
    constexpr auto a = array_repeat<3>(11);
    static_assert(a == std::array<int,3>{11,11,11});
}

这可能效率较低,但是这是否取决于您。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...