【发布时间】: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> 的指针。所以我必须要么
- 拥有导入此寄存器的类的两份副本,一份处理 uint32_t 类型,一份处理 uint64_t 类型。由于代码重复,这个解决方案显然很糟糕。
- 模板化导入此寄存器的类。在一个理想的世界中,这可能是正确的解决方案,但它并不真正适合“正常的做事方式”,其他同事可能更喜欢复制和粘贴而不是模板化这种类型的类。
- 制作一个适配器。子类
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)返回正确的类型,而不需要强制转换不是更好吗?这也可以解决您的问题。