Убедитесь, что указали c std :: массив во время компиляции - PullRequest
0 голосов
/ 04 февраля 2020

У меня есть std::array с записями, которые я хочу в указанной позиции c в соответствии с index моего Variable класса во время компиляции:

#include <string_view>
#include <array>

struct Variable
{
  size_t index;
  std::string_view name;
}

constexpr std::array<Variable, 3> myarray {{{0, "myvar1"},
                                            {1, "myvar2"},
                                            {2, "myvar3"}}};

Теперь я могу гарантировать Позиция во время компиляции со статусом c assert:

static_assert(myarray[0].index == 0);
static_assert(myarray[1].index == 1);
static_assert(myarray[2].index == 2);

Это позволяет избежать ошибок ввода:

constexpr std::array<Variable, 3> myarray {{{0, "myvar1"},
                                            {2, "myvar2"}, // wrong index for array position 1
                                            {2, "myvar3"}}};

Но это подвержено ошибкам и нарушает принцип "единого источника истина». Я хочу, например, обратную std::get<T>:

constexpr std::size_t index0 = 0;
std::set<index0>(myarray, {index0, "singen"});

Но этого не существует, как бы я достиг этого в C ++ 17?

1 Ответ

2 голосов
/ 04 февраля 2020

вы можете использовать std::get для гипотетического std::set<index0>(myarray, {index0, "singen"}):

constexpr std::size_t index0 = 0;
std::get<index0>(myarray) = {index0, "singen"};

Но, кажется, проще переделать создание массива:

constexpr std::array<Variable, 3> make_myarray()
{
    std::array<Variable, 3> res{};
    std::array<std::string_view, 3> strings = {"myvar1", "myvar2", "myvar3"};

    for (std::size_t i = 0; i != res.size(); ++i) {
        res[i] = {i, strings[i]};
    }
    return res;
}

А затем

constexpr std::array<Variable, 3> myarray = make_myarray();

Демо

Вы можете даже создать лямбду вместо обычной функции и вызывать ее напрямую:

constexpr std::array<Variable, 3> myarray = [](){
    std::array<Variable, 3> res{};
    std::array<std::string_view, 3> strings = {"myvar1", "myvar2", "myvar3"};

    for (std::size_t i = 0; i != res.size(); ++i) {
        res[i] = {i, strings[i]};
    }
    return res;
}();

Демо

или даже создать свою функцию проверки

template <std::size_t N>
constexpr bool is_valid(const std::array<Variable, N>& a) {
    for (std::size_t i = 0; i != a.size(); ++i) {
        if (a[i].index != i) {
            return false;
        }
    }
    return true;
}

constexpr std::array<Variable, 3> myarray {{{0, "myvar1"},
                                            {2, "myvar2"}, // wrong index for array position 1
                                            {2, "myvar3"}}};

static_assert(is_valid(myarray)); // Trigger here.

Демо

...