元编程,阶乘,C++,boost

metaprogramming, factorial, C++, boost

需要计算从 1 到 k 的所有数字的阶乘,并使用 boost/mpl.

将它们保存在 mpl 容器中

存储在 range_c 中的此 nums 的范围。 困难在于我必须存储所有以前的值: k! = (k-1)!*k

我认为我将在 mpl::vector_c 中存储以前的值,即每次迭代我将从源 range_c 中获取值并将其与包含在 [= 中的先前值 (k-1)! 相乘23=],但是我这段代码有很多错误:

namespace mpl = boost::mpl;
const int border = 10;
using namespace mpl;

typedef
    range_c <int, 1, border>
Numbers;

typedef vector_c<int, 1> data;

typedef
   mpl::transform
  <
    Numbers,
    data,
    push_back<data, multiplies <_, _>>,
    back_inserter
    <
      mpl::vector <>
    >
  >::type
    Factorials;

您可以使用以下内容:

namespace detail
{
    // General computation of factorial
    template <std::size_t N>
    struct factorial :
        std::integral_constant<std::size_t, N * factorial<N - 1>::value>
    {
    };

    // special case for 0
    template <>
    struct factorial<0> : std::integral_constant<std::size_t, 1u>
    {};

    // helper to create the sequence of factorial value
    template <typename T> struct factorial_seq_impl;

    template <std::size_t...Is>
    struct factorial_seq_impl<std::index_sequence<Is...>>{
        using type = std::index_sequence<factorial<Is>::value...>;
    };

}

// And finally
template <std::size_t N>
using factorial_seq =
    typename detail::factorial_seq_impl<std::make_index_sequence<N>>::type;

static_assert(std::is_same<std::index_sequence<1, 1, 2, 6, 24>, factorial_seq<5>>::value, "");

Live Demo.

阶乘 mpl 版本和向量中前 10 个结果的集合:

template <typename current, typename to, typename result>
struct calc :
    eval_if< less_equal< current, to >,
    calc< typename current::next, to, typename multiplies< result, current > >,
    result
    >::type
{};

template<typename value>
struct factorial :
    calc<int_<1>, value, int_<1> >::type
{};

template <>
struct factorial<int_<0> > :
    int_<1>::type
{};

template <>
struct factorial<int_<1> > :
    int_<1>::type
{};

template <int value>
struct factorial_c :
    factorial<int_<value> >::type
{};

struct factorial_collection_10 :
    transform<
    range_c<int, 0, 10>,
    factorial<boost::mpl::_1>,
    back_inserter<vector0<> >
    >::type
{};

测试代码:

int main()
{
    // get 5! value
    std::cout << "5! = " << factorial_c<5>::value << std::endl;

    // access 6th element of the factorial collection
    std::cout << "6! = " << at<factorial_collection_10, int_<6> >::type::value << std::endl;

    // copy factorial collection to std vector to check values at runtime
    std::vector<int> factorialVec;
    for_each< factorial_collection_10, boost::mpl::_1 >(boost::bind(static_cast<void(std::vector<int>::*)(const int&)>(&std::vector<int>::push_back), &factorialVec, boost::lambda::_1));

    std::cout << "First 10 factorial numbers: " << std::endl;
    for (std::size_t x = 0; x < factorialVec.size(); ++x)
        std::cout << x << "! = " << factorialVec[x] << std::endl;

    return 0;
}

输出:

5! = 120
6! = 720
First 10 factorial numbers:
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320

在所有实现中,为从 1 开始的每个数字计算阶乘。在任务中,我需要通过与前一个阶乘相乘来计算每个下一个阶乘。这里正确的代码:

namespace mpl = boost::mpl;
using namespace mpl;
const int border = 15;

typedef range_c<int, 1, border> nums;
typedef vector<int_<1>> data;

typedef mpl::fold<
    nums, data,
    mpl::push_back<_1, mpl::multiplies<_2, back<_1>>>
>::type Factorials;