用常量值初始化 std::array
Initializing a std::array with a constant value
我需要用一个常量值初始化 std::array
的所有元素,就像可以用 std::vector
完成的那样。
#include <vector>
#include <array>
int main()
{
std::vector<int> v(10, 7); // OK
std::array<int, 10> a(7); // does not compile, pretty frustrating
}
有没有办法优雅地做到这一点?
现在我正在使用这个:
std::array<int, 10> a;
for (auto & v : a)
v = 7;
但我想避免使用显式代码进行初始化。
唉,没有; std::array
支持 聚合初始化 但这还不够。
幸运的是你可以使用 std::fill
,甚至 std::array<T,N>::fill
,从 C++20 开始 是 优雅的,因为后者变成了 constexpr
.
您可以按照以下方式进行
std::array<int, 10> a;
a.fill(2/*or any other value*/);
或使用算法头文件中的 std::fill
。
要包含算法头文件,请使用
#include <algorithm>
使用 std::index_sequence
,你可以这样做:
namespace detail
{
template <typename T, std::size_t ... Is>
constexpr std::array<T, sizeof...(Is)>
create_array(T value, std::index_sequence<Is...>)
{
// cast Is to void to remove the warning: unused value
return {{(static_cast<void>(Is), value)...}};
}
}
template <std::size_t N, typename T>
constexpr std::array<T, N> create_array(const T& value)
{
return detail::create_array(value, std::make_index_sequence<N>());
}
随着使用
auto a = create_array<10 /*, int*/>(7); // auto is std::array<int, 10>
与 std::fill
解决方案相反,处理非默认可构造类型。
std::array
类型是支持列表初始化的聚合:
std::array<int, 10> a{2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
它还支持聚合初始化:
std::array<int, 10> a = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
这对于长数组来说既不方便又容易出错,最好使用像 Jarod42 这样的解决方案。
从 C++17 开始,您可以编写一个 constexpr 函数来有效地设置数组,因为元素访问器现在是 constexpr。此方法也适用于其他各种设置初始值的方案:
#include <array>
template<typename T, size_t N>
constexpr auto make_array(T value) -> std::array<T, N>
{
std::array<T, N> a{};
for (auto& x : a)
x = value;
return a;
}
int main()
{
auto arr = make_array<int, 10>(7);
}
我需要用一个常量值初始化 std::array
的所有元素,就像可以用 std::vector
完成的那样。
#include <vector>
#include <array>
int main()
{
std::vector<int> v(10, 7); // OK
std::array<int, 10> a(7); // does not compile, pretty frustrating
}
有没有办法优雅地做到这一点?
现在我正在使用这个:
std::array<int, 10> a;
for (auto & v : a)
v = 7;
但我想避免使用显式代码进行初始化。
唉,没有; std::array
支持 聚合初始化 但这还不够。
幸运的是你可以使用 std::fill
,甚至 std::array<T,N>::fill
,从 C++20 开始 是 优雅的,因为后者变成了 constexpr
.
您可以按照以下方式进行
std::array<int, 10> a;
a.fill(2/*or any other value*/);
或使用算法头文件中的 std::fill
。
要包含算法头文件,请使用
#include <algorithm>
使用 std::index_sequence
,你可以这样做:
namespace detail
{
template <typename T, std::size_t ... Is>
constexpr std::array<T, sizeof...(Is)>
create_array(T value, std::index_sequence<Is...>)
{
// cast Is to void to remove the warning: unused value
return {{(static_cast<void>(Is), value)...}};
}
}
template <std::size_t N, typename T>
constexpr std::array<T, N> create_array(const T& value)
{
return detail::create_array(value, std::make_index_sequence<N>());
}
随着使用
auto a = create_array<10 /*, int*/>(7); // auto is std::array<int, 10>
与 std::fill
解决方案相反,处理非默认可构造类型。
std::array
类型是支持列表初始化的聚合:
std::array<int, 10> a{2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
它还支持聚合初始化:
std::array<int, 10> a = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
这对于长数组来说既不方便又容易出错,最好使用像 Jarod42 这样的解决方案。
从 C++17 开始,您可以编写一个 constexpr 函数来有效地设置数组,因为元素访问器现在是 constexpr。此方法也适用于其他各种设置初始值的方案:
#include <array>
template<typename T, size_t N>
constexpr auto make_array(T value) -> std::array<T, N>
{
std::array<T, N> a{};
for (auto& x : a)
x = value;
return a;
}
int main()
{
auto arr = make_array<int, 10>(7);
}