Как получить факториал <a>.... факториал <b>во время выполнения? - PullRequest
2 голосов
/ 06 апреля 2019

Я хочу заполнить таблицу поиска целыми числами, вычисленными во время компиляции:

#include <iostream>
#include <type_traits>

template <int x> using number = std::integral_constant<int,x>;    
template <int n> struct factorial : number<n * factorial<n-1>::value> {};
template <> struct factorial<0> : number<1> {};

int get_factorial(int x) {
    if (x < 1) return -1;
    if (x > 5) return -1;
    static constexpr int lookup_table[] = { 
        factorial<1>::value,
        factorial<2>::value,
        factorial<3>::value,
        factorial<4>::value,
        factorial<5>::value
    };
    return lookup_table[x-1];
}

int main() {        
    int x;
    std::cin >> x;
    std::cout << get_factorial(x) << "\n";
}

Это хорошо для небольшого количества элементов, но что я могу сделать, если таблица поиска содержит большое количество элементов? Как заполнить массив без явной записи каждого элемента?

factorial только для примера. В более реалистичном сценарии я хотел бы сохранить ~ 1000 элементов в справочной таблице.

Ответы [ 2 ]

3 голосов
/ 06 апреля 2019

С C ++ 14 вы можете использовать std::integer_sequence:

template <int... S>
constexpr std::array<int, sizeof...(S)> get_lookup_table_impl(std::integer_sequence<int, S...>)
{
    return { factorial<S>::value... };
}

template <int S>
constexpr auto get_lookup_table()
{
    return get_lookup_table_impl(std::make_integer_sequence<int, S>{});
}

См. Полностью рабочий пример здесь .

Хитрость в том, что std::make_integer_sequence<int, S>{} создаст экземпляр std::integer_sequence<int, S...>.Таким образом, вспомогательная функция get_lookup_table_impl может вывести свой пакет параметров.Затем factorial<S>::value... распаковывает его и передает каждое значение S в factorial.Покрытый фигурными скобками, он может использоваться для инициализации любого типа стандартного контейнера.Я использовал std::array, но вы можете использовать все, что захотите.

1 голос
/ 06 апреля 2019

Здесь можно использовать расширение пакета параметров для инициализации массива:

#include <iostream>
#include <type_traits>
#include <utility>
template <int x> using number = std::integral_constant<int,x>;    
template <int n> struct factorial : number<n * factorial<n-1>::value> {};
template <> struct factorial<0> : number<1> {};

template<std::size_t... Is>
int get_factorial_impl(int x,std::index_sequence<Is...>)
{
    if (x < 1) return -1;
    if (x > 5) return -1;
    static constexpr int lookup_table[] = { factorial<Is+1>::value...};
    return lookup_table[x-1];
}

int get_factorial(int x)
{
    return get_factorial_impl(x,std::make_index_sequence<5>{});
}

int main() {        
    int x;
    std::cin >> x;
    std::cout << get_factorial(x) << "\n";
}
...