Подтвердить что ты не робот

Таблица поиска с помощью constexpr

Я ищу создать таблицу координат координат, например:

int a[n][2] = {{0,1},{2,3}, ... }

Для заданного n, который должен быть создан во время компиляции. Я начал изучать constexpr, но кажется, что функция, возвращающая constexpr std::vector<std::array <int, 2> >, не является опцией, поскольку я получаю:

invalid return type 'std::vector<std::array<int, 2ul> >' of constexpr function

Как создать такой массив времени компиляции?

4b9b3361

Ответ 1

Сначала я выгружу код, добавив ссылки и комментарии, где это необходимо/позже. Просто оставьте комментарий, если результат несколько близок к тому, что вы ищете.

Индексный трюк для расширения пакета (требуется здесь для применения генератора), Xeo, от этого ответа, измененный для использования std::size_t вместо unsigned.

#include <cstddef>

// by Xeo, from /questions/52917/c-concat-two-const-char-string-literals/372224#372224
template<std::size_t... Is> struct seq{};
template<std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>{};
template<std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...>{};

Функция генератора:

#include <array>

template<class Generator, std::size_t... Is>
constexpr auto generate_array_helper(Generator g, seq<Is...>)
-> std::array<decltype(g(std::size_t{}, sizeof...(Is))), sizeof...(Is)>
{
    return {{g(Is, sizeof...(Is))...}};
}

template<std::size_t tcount, class Generator>
constexpr auto generate_array(Generator g)
-> decltype( generate_array_helper(g, gen_seq<tcount>{}) )
{
    return generate_array_helper(g, gen_seq<tcount>{});
}

Пример использования:

// some literal type
struct point
{
    float x;
    float y;
};
// output support for `std::ostream`
#include <iostream>
std::ostream& operator<<(std::ostream& o, point const& p)
{  return o << p.x << ", " << p.y;  }

// a user-defined generator
constexpr point my_generator(std::size_t curr, std::size_t total)
{
    return {curr*40.0f/(total-1), curr*20.0f/(total-1)};
}

int main()
{
    constexpr auto first_array = generate_array<5>(my_generator);
    constexpr auto second_array = generate_array<10>(my_generator);

    std::cout << "first array: \n";
    for(auto p : first_array)
    {
        std::cout << p << '\n';
    }
    std::cout << "========================\n";

    std::cout << "second array: \n";
    for(auto p : second_array)
    {
        std::cout << p << '\n';
    }
}

Ответ 2

С С++ 14 вам не нужно слишком много магии шаблонов. Вот пример того, как иметь таблицу поиска для f(x) = x^3 с первой координатой, являющейся значением x, а вторая координата - значением f(x):

#include <iostream>

template<int N>
struct Table
{
    constexpr Table() : values()
    {
        for (auto i = 0; i < N; ++i)
        {
            values[i][0] = i;
            values[i][1] = i * i * i;
        }
    }
    int values[N][2];
};

int main() {
    constexpr auto a = Table<1000>();
    for (auto x : a.values)
        std::cout << "f(" << x[0] << ") = " << x[1] << '\n';
}

Ответ 3

Как использовать GNU gperf или какую-то другую утилиту генерации кода?