- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在从事的项目可以受益于在不同的大数字库之间轻松交换的可能性:GMP、OpenSSL 等。我当前的实现定义了一个模板抽象基类,我在其中实现了所有必需的运算符(只是为了有一些语法糖),我定义了所需的纯虚函数。
对于每个库,我都有一个这样的派生类:class BigNumberGmp : public BigNumberBase<BigNumberGmp>
.我知道它有点破坏 OOP,但 C++ 协方差功能限制太多,它不允许我从方法返回 BigNumberBase 对象,仅返回引用,这是非常不受欢迎的...
问题是我希望使用我的自定义包装器的代码能够与任何此类包装器一起工作:BigNumberGmp、BigNumberOpenSsl 等。为了实现这一点,我定义了 typedef BigNumberGmp BigNumber 并将其放入一些条件宏中,像这样:
#if defined(_LIB_GMP)
typedef BigNumberGmp BigNumber;
#endif
另外,我以类似的方式包含了适当的 header 。此实现要求我在编译器选项中定义 _LIB_GMP 符号。
如您所见,这是一种相当老套的技术,我并不为此感到自豪。此外,它不会以任何方式隐藏专门的类(BigNumberGmp、BigNumberOpenSsl 等)。我也可以多次定义 BigNumber 类,包装在 _LIB_XXX 条件宏中,或者我可以在 BigNumber 类中多次实现所需的方法,对于每个库,也包装在 _LIB_XXX 条件宏中。后两个想法似乎比 typedef 实现更糟糕,它们肯定会弄乱 doxygen 输出,因为它无法弄清楚为什么我有多个同名项目。我想避免使用 doxygen 预处理器,因为我仍然依赖于 _LIB_XXX 定义...
有没有优雅的设计模式可供我使用?你会如何处理这样的问题?
最佳答案
看起来你每次切换库时都要重新编译,在这种情况下你可以使用模板特化而不是继承。
选择使用哪个几乎与您拥有的一样(基于 #if
的东西),但是您将保存虚拟成员,这意味着编译器仍然可以内联,这意味着它可能显着在某些情况下更快。
首先,获取描述每个实现的结构。在这里,您可以放置在所有库中以相同方式工作的基本 API 名称。例如,如果它们都支持一个添加操作,该操作接受指向两个大数字的指针并返回一个指向包含结果的新大数字的指针,您可以执行如下操作:
(请注意,我没有通过编译器运行它,我不知道实际的 API 是什么样子,但它应该足以给出该方法的一般概念)
struct GMP {
GMP_ptr* add(GMP_ptr *l, GMP_ptr*r) {
return GMPadd(l, r);
}
};
struct OpenSSL {
OpenSSL_ptr* add(OpenSSL_ptr*, OpenSSL_ptr*) {
OpenSSL_ptr ret = NULL;
OpenSSLadd(l, r, &ret);
return ret;
}
};
现在我们可以定义一个通用父类(super class),其中包含使用这些易于映射的 API:
template< typename B, typename R >
class common {
public:
// Assume that all types have the same API
R operator + (const common &r) {
return R(B::add(l.ptr, r.ptr));
}
};
类型B是定义大数API的struct,类型R是真正的实现子类。通过像这样传入 R,我们解决了协变返回问题。
对于真正的实现,我们定义了一个模板来为我们完成工作:
template< typename B >
class big_num;
现在我们可以针对实现专门化它:
template<>
class big_num<OpenSSL> : common< OpenSSL, big_num<OpenSSL> > {
OpenSSL_ptr *ptr;
public:
big_num(OpenSSL_ptr*p)
: ptr(p) {
}
big_num(const char *s)
: ptr(OpenSSLBigNumFromString(s)) {
}
~big_num() {
OpenSSLBigNumFree(ptr)
}
};
operator +
将来自父类(super class),您现在可以像这样使用它们:
void foo() {
big_num< GMP > gmp1("123233423"), gmp2("234");
big_num< GMP > gmp3 = gmp1 + gmp2;
big_num< OpenSSL > ossl1("1233434123"), ossl2("234");
big_num< OpenSSL > ossl3 = ossl1 + ossl2;
}
这里的优点是,由于使用结构来适应相似的 API 功能和一个模板中的通用实现,因此特化之间的代码重复最少。给定 API 的细节现在在模板特化中,但没有虚拟,也没有公共(public)父类(super class)。这意味着编译器可以内联包装器中的几乎所有内容,这将使它们基本上尽可能快。
由于特化,您还有可能访问所有可能使您的单元测试更易于编写/管理的实现(您也应该能够编写它们的模板化版本)。
如果您只希望其中之一可见,那么可以这样:
#if BIGNUM=="GMP"
typedef big_num<GMP> used_big_num;
#elif BIGNUM=="OpenSSL"
typedef big_num<OpenSSL> used_big_num;
#endif
如果 header 并非始终可用,您可能还需要对特化进行保护,在这种情况下,您需要一组 HAVE_GMP_BIGNUM
和 HAVE_OPENSSL_BIGNUM
宏也是。
关于c++ - 大数库的通用包装类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10372879/
我已经花了不少时间编写我的代码(它不起作用)。这是一个欧拉计划问题,其中给定一个非常大的和来查找,然后要求打印该和的前十位数字。 (问题可以在这里找到:https://projecteuler.net
我正在构建一个基于大整数的 C 库。基本上,我正在寻找一种快速算法来将二进制表示中的任何整数转换为十进制数 我看到了 JDK 的 Biginteger.toString() 实现,但对我来说它看起来很
C++ 编程新手。有没有办法使代码更好,使其没有重复代码。 if (totalDistance < pow(10, 3)) { cout << "\nTotal (approx) travel
我正在开发一个 3D 太空游戏,它使用了大量的数学公式、导航、缓动效果、旋转、行星之间的巨大距离、物体质量等等...... 我的问题是使用数学的最佳方法是什么。我应该将所有内容都计算为整数并获得非
我尝试用 JS 的取模函数计算,但没有得到正确的结果(应该是 1)。这是一段硬编码的代码。 var checkSum = 210501700012345678131468; alert(checkSu
美好的一天我正在尝试对 10000 个数字使用快速排序,但它给我堆栈溢出错误。它适用于随机数,但不适用于递减和递增的数字。 '谢谢 void quickSort(long* array, long s
在 Codewars 上找到这个。该函数接受两个参数 A 和 B,并返回 A^B 的最后一位。下面的代码通过了前两个测试用例,但不会通过下一个测试用例。 def last_digit(n1, n2):
复制代码 代码如下: #include <stdio.h> #include <string.h> #include <stdlib.h> #include
我需要一些帮助来决定什么更好 性能 明智的。 我正在与 一起工作bigints (超过 500 万位)并且大部分计算(如果不是全部)都在将当前 bigint 加倍。所以我想知道 是否更好乘每个单元格(
我正在对字符串执行一些 mod 算术类型的操作,其中每个字符都会获得特定的初始值(取决于其 ascii)和字符串中的位置。这些数字变得非常大,因为它们的初始值为 (ascii)*26^charPos。
这个问题在这里已经有了答案: Calculating pow(a,b) mod n (14 个答案) 关闭 6 年前。 在 Javascript 中是否有获取大数模数的技巧。我用 modulo(7,
我一直在努力为我的大学完成以下作业。到目前为止,我已经多次在这项作业上得到帮助(我真的很感激)。 由于这是大学作业,我希望能提供非直接的答案,这些答案可以通过不直接解决我的作业的示例来解释概念。 作业
我正在处理无法四舍五入的大量数字。使用 Lua 的标准数学库,似乎没有方便的方法来保持超出某些内部限制的精度。我还看到有几个库可以加载以处理大数字: http://oss.digirati.com.b
我有一个数据文件 (csv) Nilsimsa哈希值。其中一些可能长达 80 个字符。我希望在 Python 中阅读它们以完成数据分析任务。有没有办法在不丢失信息的情况下在python中导入数据? 编
我是一名优秀的程序员,十分优秀!