Мне интересно, есть ли правильный способ сделать это.
Учитывая пример:
struct Test {
static std::array<unsigned, 123> data;
};
std::array<unsigned, 123> Test::data = {};
Если я хочу установить все элементы в data
вкакое-то значение, например 5.
Я мог бы сделать что-то вроде этого:
struct Test {
static std::array<unsigned, 123> data;
private:
static decltype(data) init_data_arr() {
decltype(data) arr = {};
arr.fill(5);
return arr;
}
};
std::array<unsigned, 123> Test::data = Test::init_data_arr();
Но тогда я бы выделил дополнительную память для массива и сделал бы копию для всего этого,что не кажется идеальным.
Еще один менее ресурсоемкий вариант будет выглядеть примерно так:
struct Test {
static bool is_init;
static std::array<unsigned, 123> data;
Test() {
if (!is_init) {
is_init = true;
data.fill(5);
}
}
};
bool Test::is_init = false;
std::array<unsigned, 123> Test::data = {};
Но теперь у меня есть дополнительные издержки при создании моей структуры Test.
Теперь я знаю, что вы можете инициализировать массивы pod следующим образом: std::array<int, 3> a = {1, 2, 3};
, но для массивов размером N
это быстро станет ужасно поддерживать.
Каждое решение, с которым я сталкиваюсь, просто использует функцию-член fill
в классе массива, но всегда обрабатывает массивы так, как будто они не являются статическими переменными-членами, или инициализирует их в main, и то и другое не очень помогает моей ситуации.
Редактировать: я создал этот служебный заголовок, которыйобобщает 2-й опТион.#pragma Once
#include <utility>
#include <iterator>
#include <algorithm>
#include <type_traits>
namespace Utils {
template<typename Container>
using element_type_t = std::remove_reference_t<decltype(*std::begin(std::declval<Container&>()))>;
template<class Container>
static Container create_filled_container(const element_type_t<Container>& value) {
Container container = {};
std::fill(container.begin(), container.end(), std::move(value));
return container;
}
}
Возможно, это можно улучшить еще больше, но, похоже, это работает.Использование выглядит следующим образом:
std::array<unsigned, 123> Test::data = Utils::create_filled_container<decltype(data)>(456);
, который устанавливает все элементы в соответствии с тем, что вы укажете.
Edit2: Итак, я провел еще несколько тестов и похоже на вызов функции для заполнения массива против вручнуювыполнение этого не всегда приводит к одной и той же сборке.
Я установил демо здесь !
Edit3: изменил некоторые вещи, чтобы они могли быть constexpr, вотего текущая форма:
template<class Container>
static constexpr Container create_filled_container(const element_type_t<Container>& value) {
Container container = {};
for (auto it = container.begin(); it != container.end(); ++it)
*it = value;
return container;
}
, которая теперь производит ту же сборку.