Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it legal to have an std::array of C-style array?

Tags:

c++

arrays

Can I use something like std::array<int[2][2], 2> as a substitute for int[2][2][2], just like std::array<int, 2> can be used instead of int[2]?

What I really need is maybe a statically-sized multidimensional array that

  1. Have "proper" value semantics, and
  2. Is stored contiguously in memory.

It seems that, unlike C-style arrays, std::array of std::array is not guaranteed to have fully compactified memory, as std::array may contain padding.

What are possible issues I might have if I use something like std::array<int[2][2], 2>? Perhaps this is a too vague question, but it's hard to figure out why exactly I'm not comfortable and somewhat doubtful using it for my purpose.

like image 462
Junekey Jeon Avatar asked Mar 03 '18 14:03

Junekey Jeon


1 Answers

No, it results in undefined behavior.

The value_type of a container must be Erasable from the container type, where Erasable is defined in [container.requirements.general] paragraph 15:

Given an allocator type A and given a container type X having a value_­type identical to T and an allocator_­type identical to allocator_­traits<A>​::​rebind_­alloc<T> and given an lvalue m of type A, a pointer p of type T*, an expression v of type (possibly const) T, and an rvalue rv of type T, the following terms are defined. If X is not allocator-aware, the terms below are defined as if A were allocator<T> — no allocator object needs to be created and user specializations of allocator<T> are not instantiated:

  • ...

  • T is Erasable from X means that the following expression is well-formed: allocator_traits<A>::destroy(m, p)

Because std::array is not allocator-aware, we need to check if allocator_traits<allocator<int[2][2]>>::destroy(m, p) is welll formed.

Since std::allocator has no member function destroy (deprecated in C++17), std::allocator_traits::destroy would call the (pseudo) destrutor of int[2][2] directly. This is ill-formed because int[2][2] is not a scalar type.

like image 158
xskxzr Avatar answered Oct 02 '22 03:10

xskxzr