массив constexpr и std :: initializer_list

Я пытался написать 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 и его базовый массив во время компиляции.

3

Решение

Ваш текущий код не должен компилироваться в соответствии с действующими правилами 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_lists ctors и функции-члены begin а также end не помечены constexpr, Тем не мение, уже есть предложение изменить это. Кстати, libstdc ++ уже помечает их как constexpr,

Теперь следующая проблема продолжительность жизни базового массива std::initializer_list, Это объясняется в 8.5.4p6:

Массив имеет то же время жизни, что и любой другой временный объект (12.2),
за исключением того, что инициализация объекта initializer_list из массива
продлевает время жизни массива точно так же, как привязка ссылки к
временный

Это означает, что базовый массив имеет то же время жизни, что и values объект, и истекает в конце вашего array конструктор, когда он выходит. Следовательно, _data указывает на просроченную память и _data[n] является неопределенным поведением.

5

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector