我正在尝试编写一个可以像这样使用的编译时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
及其在编译时的基础数组的行为。
答案 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和成员函数begin
和end
未标记为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]
是未定义的行为。