Я пытался написать 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. когда составлено с помощью 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
s ctors и функции-члены begin
а также end
не помечены constexpr
, Тем не мение, уже есть предложение изменить это. Кстати, libstdc ++ уже помечает их как constexpr
,
Теперь следующая проблема продолжительность жизни базового массива std::initializer_list
, Это объясняется в 8.5.4p6:
Массив имеет то же время жизни, что и любой другой временный объект (12.2),
за исключением того, что инициализация объекта initializer_list из массива
продлевает время жизни массива точно так же, как привязка ссылки к
временный
Это означает, что базовый массив имеет то же время жизни, что и values
объект, и истекает в конце вашего array
конструктор, когда он выходит. Следовательно, _data
указывает на просроченную память и _data[n]
является неопределенным поведением.
Других решений пока нет …