C++用值初始化聚合类型的std::数组

C++ initialize a std::array of aggregate types with values

本文关键字:std 类型 数组 初始化 C++      更新时间:2023-10-16

我想知道如何初始化结构的N元素std::数组。

示例:

struct SomeStruct {
uint32_t * const entry1;
uint16_t * const entry2;
uint16_t * const entry3;
};

可以通过以下方式进行初始化:

static const std::array<SomeStruct , 2> arr
{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
// nullptr just for example, would be addresses of real variables in the project

但这并不是我所需要的,因为下面的语句在没有任何警告或其他东西的情况下也能正常工作,因此使元素默认初始化。

static const std::array<SomeStruct , 2> arr
{nullptr, nullptr, nullptr, nullptr};

我需要的是严格检查编译器是否所有元素都已初始化,语法类似于

static const std::array<SomeStruct , 2> arr
{{nullptr, nullptr, nullptr}, {nullptr, nullptr, nullptr}};

是否可以强制C++检查要初始化的加积类型的所有元素?

坦克你!

但这并不是我所需要的,因为下面的语句在没有任何警告或其他事情的情况下也能正常工作,因此使元素默认初始化。

它不会使元素默认初始化。关于聚合初始化的cppreference,强调挖掘:

如果初始值设定项子句的数量小于成员的数量,或者初始值设定项列表完全为空,则剩余成员将被值初始化如果引用类型的成员是这些剩余成员中的一个,则程序格式不正确。

C++11中的确切措辞发生了变化,但不会影响您的情况。

因此,如果您想将所有初始化为nullptr,只需使用

static const std::array<SomeStruct , 2> arr{};

如果您希望在任何元素未显式初始化时发出警告,那么您就没有可移植的解决方案。编译器无法知道数组其余部分的值初始化是否是有意的。

一个不可移植的解决方案:GCC有一个警告标志-Wmissing-field-initializers

warning: missing initializer for member 'SomeStruct::entry2' [-Wmissing-field-initializers]
{nullptr, nullptr, nullptr, nullptr};
^

您可以使用std::make_arraystatic_assert作为结果类型。然而,std::make_array只是一个建议,但这里有一个参考实现。

namespace details {
template<class> struct is_ref_wrapper : std::false_type {};
template<class T> struct is_ref_wrapper<std::reference_wrapper<T>> : std::true_type {};
template<class T>
using not_ref_wrapper = std::experimental::negation<is_ref_wrapper<std::decay_t<T>>>;
template <class D, class...> struct return_type_helper { using type = D; };
template <class... Types>
struct return_type_helper<void, Types...> : std::common_type<Types...> {
static_assert(std::experimental::conjunction_v<not_ref_wrapper<Types>...>,
"Types cannot contain reference_wrappers when D is void");
};
template <class D, class... Types>
using return_type = std::array<typename return_type_helper<D, Types...>::type,
sizeof...(Types)>;
}
template < class D = void, class... Types>
constexpr details::return_type<D, Types...> make_array(Types&&... t) {
return {std::forward<Types>(t)... };
}