【问题标题】:C++ initialize a std::array of aggregate types with valuesC++ 使用值初始化聚合类型的 std::array
【发布时间】:2017-02-01 09:02:42
【问题描述】:

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

例子:

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++ 检查是否要初始化 aggragte 类型的所有元素?

谢谢你!

【问题讨论】:

  • 如果你这样做 aggregate initialization 你实际上可以让列表为 empty 并且所有元素都将被默认初始化。
  • 为了澄清我之前的评论,编译器遵循 C++ 规范,它允许您在初始化中使用更少的成员或元素,并且不需要警告它。如果您想强制对所有元素和所有成员进行显式初始化,那么您可能应该使用一个静态分析器,它可以检测到这一点并给出警告。
  • 你用的是什么编译器?你确定没有可选的警告吗?

标签: c++ c++11 initialization stdarray


【解决方案1】:

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

它不会让元素默认初始化。 cppreference aggregate initialization,强调我的:

如果初始化子句的数量少于成员的数量或初始化列表完全为空,则剩余的成员被值初始化。如果引用类型的成员是剩余的这些成员之一成员们,程序格式不正确。

确切的措辞在 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};
                                   ^

【讨论】:

    【解决方案2】:

    您可以使用 std::make_arraystatic_assert 结果类型。 std::make_array 只是一个提议,但有一个参考实现 here

    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)... };
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      • 1970-01-01
      • 2017-10-27
      • 2017-12-18
      • 2017-02-27
      • 1970-01-01
      相关资源
      最近更新 更多