代码之家  ›  专栏  ›  技术社区  ›  OJW

只使用某些数据类型的字段的C++模板函数?

  •  4
  • OJW  · 技术社区  · 15 年前

    有可能有一个C++模板函数,它可以根据它的输入数据访问不同的字段 类型 输入的数据被传递给它了吗?

    例如,我有表单代码:

    typedef struct
    {
      int a;
      int b;
    }s1;
    
    typedef struct
    {
      int a;
    }s2;
    
    template <class VTI_type> void myfunc(VTI_type VRI_data, bool contains_b)
    {
      printf("%d", VRI_data.a);
    
      if(contains_b) // or suggest your own test here
        printf("%d", VRI_data.b); // this line won't compile if VTI_type is s2, even though s2.b is never accessed
    }
    
    void main()
    {
      s1 data1;
      data1.a = 1;
      data1.b = 2;
      myfunc <s1> (data1, true);
    
      s2 data2;
      data2.a = 1;
      myfunc <s2> (data2, false);
    }
    

    所以我们要使用来自许多不同数据类型的字段A,这很好。

    但是,有些数据也有一个需要使用的字段B,但是如果模板知道它正在查找不包含字段B的数据类型,则需要删除访问字段B的代码。

    (在我的示例中,结构是外部API的一部分,因此无法更改)

    4 回复  |  直到 15 年前
        1
  •  5
  •   peterchen    15 年前

    要详细说明模板专业化的建议使用:

    template <class T> void myfunc(T data)
    {  
        printf("%d", VRI_data.a);  
    }
    
    // specialization for MyClassWithB:
    template <>
    void myfunc<MyClassWithB>(MyClassWithB data)
    {
        printf("%d", data.a);  
        printf("%d", data.b); 
    }
    

    但是,这要求每个类都有一个专门化,没有对B的“自动检测”。而且,您重复了很多代码。

    您可以在助手模板中考虑到“有B”方面。简单演示:

    // helper template - "normal" classes don't have a b
    template  <typename T>
    int * GetB(T data) { return NULL; }  
    
    // specialization - MyClassWithB does have a b:
    template<>
    int * GetB<MyClassWithB>(MyClassWithB data) { return &data.b; }
    
    // generic print template
    template <class T> void myfunc(T data)
    {  
        printf("%d", VRI_data.a);  
        int * pb = GetB(data);
        if (pb)
          printf("%d", *pb); 
    }
    
        2
  •  3
  •   EFraim    15 年前

    解决方案1:可以使用模板 专业化 . 专业化可以根据每堂课进行,也可以根据一些更一般的特点进行。

        3
  •  0
  •   Naveen    15 年前

    如果不想对代码中的s1&s2专门化进行硬编码,那么可以执行以下操作:

    typedef struct
    {
      int a;
      int b;
    }s1;
    
    typedef struct
    {
      int a;
    }s2;
    
    template <class T, bool contains_b> 
    struct MyFunc
    {
    
        void operator()(T data)
        {
            printf("%d", data.a);
        }
    
    };
    
    
    template <class T> 
    struct MyFunc<T, true>
    {
        void operator()(T data)
        {
            printf("%d", data.a);
            printf("%d", data.b); 
    
        }
    };
    
    template<class T, bool contains_b>
    void myFunc(T t)
    {
        MyFunc<T, contains_b> m;
        m(t);
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
     s1 data1;
      data1.a = 1;
      data1.b = 2;
    
      myFunc<s1,true>(data1) ;
    
      s2 data2;
      data2.a = 1;
      myFunc<s2,false>(data2);
      return 0;
    }
    
        4
  •  0
  •   OJW    15 年前

    为了详细说明其他人的答案,最好的方法似乎是不在多个模板中重复相同的代码,只需要有一个“额外的东西”函数(对于大多数数据类型来说是空的,但是对于任何有额外数据的对象都包含代码),其中“模板专业化”选择为e运行哪个“额外的东西”函数。ACH数据类型。

    更新代码:

    typedef struct
    {
      int a;
      int b;
    }s1;
    
    typedef struct
    {
      int a;
    }s2;
    
    template <class VTI_type> void extraStuff(VTI_type VRI_data)
    {
    }
    
    template <> void extraStuff<s1>(s1 VRI_data)
    {
      printf(" and b = %d\n", VRI_data.b);
    }
    
    template <class VTI_type> void myfunc(VTI_type VRI_data)
    {
      printf("a = %d\n", VRI_data.a);
      extraStuff(VRI_data);
    }
    
    void main()
    {
      s1 data1;
      data1.a = 1;
      data1.b = 2;
      myfunc <s1> (data1);
    
      s2 data2;
      data2.a = 1;
      myfunc <s2> (data2);
    }