Why is std::array still an agregate?

123 views
Skip to first unread message

jgot...@gmail.com

unread,
Sep 2, 2015, 9:11:40 PM9/2/15
to ISO C++ Standard - Discussion
With the improvements from C++11 (defaulted functions, initializer-lists, and loosened POD rules) is there any reason why std::array should still be an aggregate?


Joe Gottman


David Krauss

unread,
Sep 2, 2015, 10:33:07 PM9/2/15
to std-dis...@isocpp.org

On 2015–09–03, at 9:11 AM, jgot...@gmail.com wrote:

With the improvements from C++11 (defaulted functions, initializer-lists, and loosened POD rules) is there any reason why std::array should still be an aggregate?

std::array stores its contents as a member C-style array. It is difficult to initialize a C-style array from an initializer_list.

If you want to do the exercise of implementing a constructor-based array (it may be very instructive), and you succeed, then by all means write a proposal.

Note that given constructors, the classic initialization syntax with doubled braces will still work, but it will require an accessible element move constructor. Guaranteed copy elision would fix that.

Columbo

unread,
Sep 3, 2015, 11:18:10 AM9/3/15
to ISO C++ Standard - Discussion
Am Donnerstag, 3. September 2015 04:33:07 UTC+2 schrieb David Krauss:
It is difficult to initialize a C-style array from an initializer_list.
Yeah, it's not that simple. And AFAICS it requires unnecessary copies (moving from initializer_list is yet another issue), as it isn't possible to extract the length of the list as a constant inside an initializer-list constructor?
Runtime dispatch of constructors could be helpful here.

How about this sketch?
template <typename T, std::size_t N>
struct array {
private:
 T arr_
[N];

 
// Not default constructible. Requires that ilist covers every element.
 
template <std::size_t... indices>
 
constexpr array(std::bool_constant<false>, std::index_sequence<indices...>, std::initializer_list<T> ilist)
 
: arr_{ilist.begin()[indices]...}
 
{}
 
template <std::size_t... indices>
 
constexpr array(std::bool_constant<true>, std::index_sequence<indices...>, std::initializer_list<T> ilist)
 
: arr_{indices>=ilist.end()-ilist.begin()? static_cast<T const&>(T{}) : ilist.begin()[indices]...}
 
{}

public:
 
constexpr array(std::initializer_list<T> ilist)
 
: array(std::is_default_constructible<T>{}, std::make_index_sequence<N>{},
        ilist
.end()-ilist.begin() >= N*(not std::is_default_constructible<T>{})?
          ilist
: throw std::length_error("") ) {}


 
constexpr array() = default;
};

However, I don't see why initializer_list is even necessary; At the moment, the following implementation works just as well:

template <typename T, std::size_t N>
struct array {
private:
 T arr_
[N];

 
template <std::size_t... indices>
 
constexpr array(std::index_sequence<indices...>, T (&&arr)[sizeof...(indices)])
 
: arr_{std::move(arr[indices])...}
 
{}

public:
 
template <std::size_t M>
 
constexpr array(T (&&arr)[M])
 
: array(std::make_index_sequence<M>{}, std::move(arr)) {}

 
constexpr array() = default;
};


Note that given constructors, the classic initialization syntax with doubled braces will still work, but it will require an accessible element move constructor.

I don't quite get why the double-braced syntax will require any more than the single-braced one. 

Columbo

unread,
Sep 3, 2015, 11:20:35 AM9/3/15
to ISO C++ Standard - Discussion
Sorry, forgot to mention that the latter implementation solely works with the double-braced form, making it unusable as a replacement for array.
Reply all
Reply to author
Forward
0 new messages