2013-04-10 118 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

相關問題