【c++】用元编程的方式实现两个长整数的加法

需求

考虑两个 10 进制非负整数的相加,如:199 + 1 = 200,35635368953573875834674647 + 3579847859469476976 = 35635372533421735304151623 。

由于该整数的长度可能超过c++基本类型的范围,因此需要通过数组的方式来存储,并计算相加的结果。

要求不运行代码即可得出结果

思路

  1. 定义模板类Cont,表示数组,整数的每一位都是数组元素。
  2. 定义打印类print,其成员函数fun()可以依次打印数组的值。
  3. 定义翻转数组的类Reverse,可实现整数的翻转,即:低位在前,高位在后。
  4. 实现加法逻辑,考虑进位和不同长度的整数相加。
  5. 调用之前实现的数组翻转元函数,将结果数组翻转,确保高位位于数组的开头,低位位于数组的结尾。
  6. 调用之前实现的 print 函数,打印输出结果。

源代码

#include <iostream>
using namespace std;

// 定义数组
template <unsigned... t>
struct Cont;

// 打印编译器的数组
template <typename T>
struct print;

template <unsigned T1, unsigned... T>
struct print<Cont<T1, T...>>
{
    inline static void fun()
    {
        cout << T1;
        print<Cont<T...>>::fun();
    }
};

template <>
struct print<Cont<>>
{
    inline static void fun()
    {
        cout << endl;
    }
};

// 翻转数组
template <typename... T>
struct Reverse;

template <unsigned... tP, unsigned t, unsigned... tR>
struct Reverse<Cont<tP...>, Cont<t, tR...>>
{
    using type = typename Reverse<Cont<t, tP...>, Cont<tR...>>::type;
};

template <unsigned... tP>
struct Reverse<Cont<tP...>, Cont<>>
{
    using type = Cont<tP...>;
};

// 数组按位相加
template <typename T1, typename T2, typename T3, typename T4>
struct Plus;

template <unsigned T, typename = void>
struct PlusExt;

template <unsigned T>
struct PlusExt<T, std::enable_if_t<(T < 10)>>
{
    constexpr static unsigned give = 0;
    constexpr static unsigned tmp = T;
};

template <unsigned T>
struct PlusExt<T, std::enable_if_t<(T >= 10)>>
{
    constexpr static unsigned give = 1;
    constexpr static unsigned tmp = T - 10;
};

template <unsigned t1, unsigned... tR1, unsigned t2, unsigned... tR2, unsigned carry, unsigned... res>
struct Plus<Cont<res...>, Cont<carry>, Cont<t1, tR1...>, Cont<t2, tR2...>>
{
    constexpr static unsigned tmp = PlusExt<t1 + t2 + carry>::tmp;
    constexpr static unsigned give = PlusExt<t1 + t2 + carry>::give;

    using type = typename Plus<Cont<res..., tmp>, Cont<give>, Cont<tR1...>, Cont<tR2...>>::type;
};

// t1数组的长度大于t2数组
template <unsigned... res, unsigned carry, unsigned t, unsigned... tR>
struct Plus<Cont<res...>, Cont<carry>, Cont<t, tR...>, Cont<>>
{
    constexpr static unsigned tmp = PlusExt<t + carry>::tmp;
    constexpr static unsigned give = PlusExt<t + carry>::give;
    using type = typename Plus<Cont<res..., tmp>, Cont<give>, Cont<tR...>, Cont<>>::type;
};

// t1数组的长度小于t2数组
template <unsigned... res, unsigned carry, unsigned t, unsigned... tR>
struct Plus<Cont<res...>, Cont<carry>, Cont<>, Cont<t, tR...>>
{
    constexpr static unsigned tmp = PlusExt<t + carry>::tmp;
    constexpr static unsigned give = PlusExt<t + carry>::give;
    using type = typename Plus<Cont<res..., tmp>, Cont<give>, Cont<>, Cont<tR...>>::type;
};

template <typename T1, typename T2>
struct LastResult;

template <unsigned... result, unsigned Carbit>
struct Plus<Cont<result...>, Cont<Carbit>, Cont<>, Cont<>>
{
    using type = typename LastResult<Cont<Carbit>, Cont<result...>>::result;
};

template <unsigned car_bit, unsigned... input>
struct LastResult<Cont<car_bit>, Cont<input...>>
{
    using result = std::conditional_t<car_bit, Cont<car_bit, input...>, Cont<input...>>;
};

int main()
{
    using a1 = Cont<1, 9, 9>;
    using a2 = Cont<1>;

    using a1R = Reverse<Cont<>, a1>::type;
    using a2R = Reverse<Cont<>, a2>::type;

    using a1Rplusa2R = Plus<Cont<>, Cont<0>, a1R, a2R>::type;
    using a1Plusa2 = Reverse<Cont<>, a1Rplusa2R>::type;
    print<a1Plusa2>::fun();

    return 0;
}

结果展示

代码写好后软件自动提示结果(IDE为vscode),编译前就可显示出来。
在这里插入图片描述

总结

元编程是一种强大的编程技术,能在编译期就完成部分软件功能,从而达到提高软件执行效率、验证代码逻辑和数据规范等功能。

但元编程的编码方式比较特殊,需要花时间练习。

以上元编程代码中用到了以下技巧:

  • 类模板
  • 变长模板
  • 类模板的特化和限制
  • 元编程的分支和循环语句
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值