Constexpr array and std :: initializer_list

I was trying to write a compile-time valarray that could be used like this:

constexpr array<double> a = { 1.0, 2.1, 3.2, 4.3, 5.4, 6.5 };

static_assert(a[0] == 1.0, "");
static_assert(a[3] == 4.3, "");

static_assert(a.size() == 6, "");


I was able to do it with the following implementation and it works fine (as of GCC 4.7):

#include <initializer_list>

template<typename T>
struct array

        const std::size_t _size;
        const T* _data;


        constexpr array(std::initializer_list<T> values):

        constexpr auto operator[](std::size_t n)
            -> T
            return _data[n]

        constexpr auto size() const
            -> std::size_t;
            return _size;


Even though it works great for me, I am not sure about the behavior std::initializer_list

and may use some of them that are undefined.


for a constructor std::initializer_list

, begin

and size

great, even if it's not strictly speaking C ++ 11, since N3471 was recently adopted and made it to the standard.

As far as undefined behavior is concerned, I'm not sure if the underlying array will std::initializer_list

live, and if not, is there an average so that it lasts longer than just the constructor array's

. What do you think?

EDIT: I may not have been clear, but I really don't need a real array. I'm really interested in the behavior of std::initializer_list

and its underlying array at compile time.


source to share

1 answer

Your current code shouldn't compile according to current C ++ 11 rules. When compiled with clang 3.2 I get the following error:

source.cpp:33:28: error: constexpr variable 'a' must be initialized by a constant
constexpr array<double> a = { 1.0, 2.1, 3.2, 4.3, 5.4, 6.5 };
                        ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


This is because std::initializer_list

ctors and member functions are begin

and are end

not tagged constexpr

. However , there is already a proposal to change this . BTW, libstdc ++ already marks this as constexpr


Now the next problem is the lifetime of the underlying array std::initializer_list

. This is explained in 8.5.4p6:

An array has the same lifetime as any other temporary object (12.2), except that initializing an initializer_list object from an array extends the lifetime of the array just like binding a reference to a temporary one.

This means that the underlying array has the same lifetime as the object values

and expires at the end of your constructor array

when it exits. Therefore it _data

points to expired memory and _data[n]

- behavior is undefined.



All Articles