【问题标题】:Template "Adapters" in C++C++ 中的模板“适配器”
【发布时间】:2011-08-20 23:09:12
【问题描述】:

我目前在处理模板类时遇到问题。在我目前正在使用的代码库中,我们有这样一行:

Register<uint32_t>* myReg = static_cast<Register<uint32_t>*>(importItemPtr(someGlobalIdString));

其中 importItemPtr 负责根据标识字符串将 void* 返回到某个全局集合中的项目。

问题是这段代码现在将在一个平台上运行,其中 someGlobalIdString 引用的对象将不再是 Register<uint32_t> 类型,而是 Register<uint64_t>。这是必须在运行时做出的决定。因为我使用的是模板化类型,所以我不能有一个可以指向Register<uint32_t>Register<uint64_t> 的指针。所以我必须要么

  1. 拥有导入此寄存器的类的两份副本,一份处理 uint32_t 类型,一份处理 uint64_t 类型。由于代码重复,这个解决方案显然很糟糕。
  2. 模板化导入此寄存器的类。在一个理想的世界中,这可能是正确的解决方案,但它并不真正适合“正常的做事方式”,其他同事可能更喜欢复制和粘贴而不是模板化这种类型的类。
  3. 制作一个适配器。子类Register<uint64_t> 创建一个新类,该类接受Register<uint32_t> 作为构造函数,本质上只是包装该寄存器并返回64 位值而不是32。重写消费类以始终使用64 位版本以及何时使用提供 32 位版本的平台只是包装它。上面的代码段看起来像这样:

适配器:

class Reg32to64Adapter : public Register<uint64_t> { ... }

消费类:

Register* myReg; if( is32bitPlatform ) { Register* my32Reg = static_cast*>(importItemPtr(someGlobalIdString)); myReg = new Reg32to64Adapter(my32Reg); }else { myReg = static_cast*>(importItemPtr(someGlobalIdString)); } //Go on manipulating myReg

有没有更好的解决方案?一些我不知道的设计模式?

【问题讨论】:

  • 为什么你的平台的位数不是编译时间常数?
  • 看起来有人在static_cast 之后吃了你的源代码块。无论如何……这是一个非常奇怪的问题。为什么必须记住一个值是 32 位还是 64 位?如果它是运行时变量,它应该是Register 的数据成员,而不是模板参数。
  • 如果importItemPtr(someGlobalIdString) 返回正确的类型,而不需要强制转换不是更好吗?这也可以解决您的问题。

标签: c++ templates


【解决方案1】:

尝试使用 Bridge 模式,其中 Implementor 是常用操作的集合,而专业化是 ConcreteImplementor。

http://en.wikipedia.org/wiki/Bridge_pattern

可能不是最好的解决方案(过度设计),所以请在使用前分析它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 2017-03-14
    相关资源
    最近更新 更多