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
{
private:
const std::size_t _size;
const T* _data;
public:
constexpr array(std::initializer_list<T> values):
_size(values.size()),
_data(values.begin())
{}
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.
constexpr
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
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
expression
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.
source to share