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, "");
我设法用以下实现来做它并且它工作正常(使用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构造函数,begin并且size很好,即使它不是严格来说C++ 11,因为N3471最近被采用并使其达到标准.
关于未定义的行为,我不确定std::initializer_list遗嘱的基础数组是否存在,是否有一个意思是让它比只有array's构造函数更长寿.你怎么看?
编辑:我可能不太清楚,但我真的不关心实际的阵列.我真正感兴趣的是std::initializer_list编译时的行为及其底层数组.
您当前的代码不应该根据当前的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 };
                        ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这是因为std::initializer_lists ctors和成员函数begin并end没有标记constexpr.但是,已经提出了改变这一点的建议.BTW,libstdc ++已将这些标记为constexpr.
现在下一个问题是底层数组的生命周期std::initializer_list.这在8.5.4p6中解释:
该数组与任何其他临时对象(12.2)具有相同的生命周期,除了从数组初始化initializer_list对象扩展了数组的生命周期,就像绑定对临时对象的引用一样.
这意味着底层数组与values对象具有相同的生命周期,并在array构造函数退出时到期.因此,_data指向过期的内存并且_data[n]是未定义的行为.