constexpr数组和std :: initializer_list

时间:2013-04-10 22:20:34

标签: c++ c++11 compile-time initializer-list constexpr

我正在尝试编写一个可以像这样使用的编译时valarray:

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, "");

我设法通过以下实现来完成它并且工作正常(使用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;
        }
};

即使它对我来说很好,但我不确定std::initializer_list的行为,并且可能会使用一些未定义的行为。

constexpr std::initializer_list构造函数,beginsize很好,即使它严格来说不是C ++ 11,因为N3471最近被采纳并进入了标准。

关于未定义的行为,我不确定std::initializer_list的基础数组是否存在,或者是否存在,是否存在使其比仅array's构造函数更长寿的意思。你觉得怎么样?

编辑:我可能不太清楚,但我并不关心实际的数组。我真正感兴趣的是std::initializer_list及其在编译时的基础数组的行为。

1 个答案:

答案 0 :(得分:5)

根据当前的C ++ 11规则,您当前的代码不应编译compiled with clang 3.2时出现以下错误:

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 };
                        ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

这是因为std::initializer_list的ctors和成员函数beginend未标记为constexpr。但是,there already is a proposal to change this。顺便说一句,libstdc ++已将这些标记为constexpr

现在,下一个问题是std::initializer_list基础数组的生命周期。这在8.5.4p6中解释:

  

该数组的生命周期与任何其他临时对象(12.2)相同,   除了从数组初始化initializer_list对象   延长数组的生命周期,就像绑定引用一样   暂时的。

这意味着底层数组与values对象具有相同的生命周期,并在array构造函数退出时到期。因此,_data指向过期的内存,_data[n]是未定义的行为。