Шаблонная функция C ++, которая использует поля, присутствующие только в некоторых типах данных? - PullRequest
4 голосов
/ 17 июля 2009

Возможно ли иметь шаблонную функцию 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 ]

5 голосов
/ 17 июля 2009

Для разработки предложенного использования шаблона специализации:

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 Кроме того, вы повторяете много кода.

Вы можете выделить этот аспект «иметь» в шаблоне помощника. Простая демонстрация:

// 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); 
}
3 голосов
/ 17 июля 2009

Решение 1: Вы можете использовать шаблон специализация . Специализация может быть выполнена для каждого класса или по более общей характеристике.

0 голосов
/ 17 июля 2009

Чтобы уточнить ответы других людей, кажется, что лучший способ сделать это без дублирования одного и того же кода в нескольких шаблонах - это просто иметь функцию «extra stuff» (пустую для большинства типов данных, но содержащую код для любых объекты, которые имеют дополнительные данные), где «специализация шаблона» выбирает, какую функцию «дополнительного материала» запустить для каждого типа данных.

Обновленный код:

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);
}
0 голосов
/ 17 июля 2009

Если вы не хотите жестко кодировать специализацию 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...