2013-04-10 56 views
2

我想写可以这样使用的编译时的valarray:constexpr阵列和std :: initializer_list

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

我设法用下面的实施做到这一点,它工作正常(与海湾合作委员会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的行为,可能会使用一些是未定义的行为。

constexprstd::initializer_list构造,beginsize是好的,即使它不是严格意义上讲C++ 11日以来N3471最近得到了采纳,并作出了规范。

关于未定义的行为,我不确定std::initializer_list的底层数组是否会存活,如果不存在,是否有意思是让它的存活时间比只有array's的构造函数长。你怎么看?

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

回答

4

根据当前的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小号构建函数和成员函数beginend没有标签constexpr。但是,there already is a proposal to change this。顺便说一句,libstdC++已经将这些标记为constexpr

现在,下一个问题是std::initializer_list底层阵列的寿命。这在8.5.4p6说明:

The array has the same lifetime as any other temporary object (12.2), except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary.

这意味着潜在的阵列具有相同的寿命作为values对象,并且在您的array构造的届满退出时。因此,_data指向已过期的内存,并且_data[n]是未定义的行为。

+1

好的,谢谢,我找不到任何关于寿命:) 我已经知道了'constexpr'标准的revelant一部分,这就是为什么我跟这没有只得到了建议,但也对N3471被录取了。 – Morwenn 2013-04-11 06:37:57

相关问题