constexpr数组和std :: initializer_list

Mor*_*enn 4 c++ compile-time initializer-list constexpr c++11

我试图编写一个可以像这样使用的编译时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, "");
Run Code Online (Sandbox Code Playgroud)

我设法用以下实现来做它并且它工作正常(使用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;
        }
};
Run Code Online (Sandbox Code Playgroud)

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

constexpr对于std::initializer_list构造函数,begin并且size很好,即使它不是严格来说C++ 11,因为N3471最近被采用并使其达到标准.

关于未定义的行为,我不确定std::initializer_list遗嘱的基础数组是否存在,是否有一个意思是让它比只有array's构造函数更长寿.你怎么看?

编辑:我可能不太清楚,但我真的不关心实际的阵列.我真正感兴趣的是std::initializer_list编译时的行为及其底层数组.

Jes*_*ood 5

您当前的代码不应该根据当前的C++ 11规则进行编译.当铿锵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 };
                        ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

这是因为std::initializer_lists ctors和成员函数beginend没有标记constexpr.但是,已经提出了改变这一点的建议.BTW,libstdc ++已将这些标记为constexpr.

现在下一个问题是底层数组的生命周期std::initializer_list.这在8.5.4p6中解释:

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

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