模板之型别对型别的映射

╰半夏微凉° 2022-08-14 01:35 187阅读 0赞

假设 Widget 类定义是我们不能修改的类型:

  1. class Widget
  2. {
  3. public:
  4. Widget(int arg, int i = -1)
  5. {
  6. }
  7. ....
  8. };

现在要通过 Create 函数来组一个统一的接口构造对象包括Widget对象和其他对象:

  1. template <class T class U>
  2. T* Create(const U& arg)
  3. {
  4. return new T(arg);
  5. }

如何特化Create() ,使它能够独特处理Widget,简单方案是写出一个 CreateWidget() 来专门处理,那么不能达到我们统一接口 Create() 的目的。

因为无法偏特化一个函数,则无法写出下面代码:

  1. // illegal code, 无法偏特化一个函数
  2. template <class U>
  3. Widget* Create<Widget, U>(const U& arg)
  4. {
  5. return new Widget(arg, -1);
  6. }

但我们还有一样工具可用:重载

  1. // 重载机制, 这种机制会轻易构造未被使用的复杂对象,造成额外开销
  2. template <class T, class U>
  3. T* Create(const U& arg, T dummy)
  4. {
  5. return new T(arg);
  6. }
  7. template <class U>
  8. Widget* Create(const U& arg, Widget dummy)
  9. {
  10. return new Widget(arg, -1);
  11. }

幸好,我们有另一种方法减小重载所带来的额外开销:

  1. // 轻量级机制来传递“型别” T 的信息到 Create() 中
  2. // 它没有任何数值,但不同型别却足以区分各个 Type2Type 实体
  3. template <typename T>
  4. struct Type2Type
  5. {
  6. typedef T OriginalType;
  7. };
  8. template <class T, class U>
  9. T* Create(const U& arg, Type2Type<T>)
  10. {
  11. return new T(arg);
  12. }
  13. template <class U>
  14. Widget* Create(const U& arg, Type2Type<Widget>)
  15. {
  16. return new Widget(arg, -1);
  17. }

测试:

  1. int main()
  2. {
  3. // Type2Type
  4. string *pStr = Create("hello", Type2Type<string>());
  5. Widget *pW = Create(100, Type2Type<Widget>());
  6. return 0;
  7. }

发表评论

表情:
评论列表 (有 0 条评论,187人围观)

还没有评论,来说两句吧...

相关阅读

    相关 行为--模板模式

    概念 -------------------- 用一个抽象类定义一些方法作为实现某个功能的模板(一般设为final),并将模板方法中某些步骤的实现推迟到子类中,使子类可