How to get factorial<a>…factorial<b> at runtime?

Deadly 提交于 2020-01-15 03:16:10

问题


I want to fill a look up table with integers computed at compile time:

#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";
}

This is fine for small number of elements, but what can I do when the look up table contains a large number of elements? How to populate the array without writing each element explicitly?

The factorial is only for the example. In a more realistic scenario I would like to store ~1000 elements in the lookup table.


回答1:


With C++14 you can use 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>{});
}

See a fully working example here.

The trick is that std::make_integer_sequence<int, S>{} will create an instance of std::integer_sequence<int, S...>. So, the helper function get_lookup_table_impl is able to deduce its parameter pack. Then, factorial<S>::value... unpacks it and passes each value of S to factorial. Covered with curly braces, this can be used to initialize any kind of std container. I used std::array, but you can use whatever you want.




回答2:


A paramater pack expansion for array initialization can be used here:

#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";
}


来源:https://stackoverflow.com/questions/55543776/how-to-get-factoriala-factorialb-at-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!