Как принять шаблон mixin в качестве аргумента?

Учитывая структуру миксина шаблона C ++, как я могу написать функцию, которая принимает миксин с определенным компонентом? В этом примере, как я могу дать withAandB в worksWithA()?

struct Base {};

template <class T>
struct HasA : T
{
int A;
};

template <class T>
struct HasB : T
{
int B;
};

void WorksWithA(HasA<Base> &p)
{
p.A++;
}

void WorksWithAandB(HasA<HasB<Base> > &p)
{
p.A++;
p.B++;
}

int _tmain(int argc, _TCHAR *argv[])
{
HasA<Base> withA;
HasA<HasB<Base> > withAandB;

WorksWithA(withA); // OK
WorksWithAandB(withAandB); // OK
WorksWithA(withAandB); // KO, no conversion available

return 0;
}

Даже если оставить в стороне проблему строительства или смешанного заказа (HasA<HasB<Base>> против HasB<HasA<Base>>), Я не вижу хорошего способа написания этой функции, кроме создания шаблона тоже.

В настоящее время я нахожусь в среде без C ++ 11, но мне было бы интересно, если современный C ++ предоставляет решение для этого.

Большое спасибо!

4

Решение

Вы можете сделать WorksWithA функция шаблона, которая принимает любой класс, заключенный в HasA:

template<typename T>
void WorksWithA(HasA<T> &p)
{
p.A++;
}

В этом случае ваш код компилируется без ошибок.

2

Другие решения

Я думаю, что вы должны сделать свой шаблон функций, а?

template <class T>
void WorksWithA(HasA<T> &p)
{
p.A++;
}

template <class T>
void WorksWithAandB(HasA<HasB<T> > &p)
{
p.A++;
p.B++;
}

поскольку HasA<HasB<Base>> никоим образом не конвертируется в HasA<Base>,

2

Как уже отмечали другие, эти функции, вероятно, лучше использовать в качестве шаблонов. Однако, пока вы это делаете, вы также можете удалить некоторое дублирование кода:

template<class B>
void WorksWithA(HasA<B> &p)
{
p.A++;
}

template<class B>
void WorksWithB(HasA<B> &p)
{
p.B++;
}

template<class Has>
void WorksWithAandB(Has &p)
{
WorksWithA(p);
WorksWithB(p);
}

Вот WorksWithAAndB называет другие типы. Следовательно:

  1. Вы повторно используете код.
  2. Вы повторно используете проверки типов типов, переданные компилятору WorksWithA а также WorksWithB для типа, переданного в WorksWithAAndB,
2

Вы должны сделать WorksWithA шаблон функции; нет другого пути. Думаю об этом: WorksWithA работает с любой тип, который имеет HasA Mixin. Это можно выразить только с помощью шаблонов.

1

Также в случае HasA а также HasB имеют значение интерфейсов, рассмотрите возможность использования наследования для решения этой проблемы:

struct HasA
{
int A;
virtual ~HasA() = default;
};

struct HasB
{
int B;
virtual ~HasB() = default;
};

struct HasAB : HasA, HasB
{
};

struct Base : HasAB
{};

void WorksWithA(HasA &p)
{
p.A++;
}

void WorksWithAandB(HasAB &p)
{
p.A++;
p.B++;
}

Здесь вы можете позвонить WorkWithA с объектом любого класса, реализующего WithA интерфейс и WorksWithAandB с объектом любого класса реализации HasAB интерфейс.

PS: к сожалению, в этом примере звонить невозможно WorksWithAandB с объектом класса, реализующим оба HasA а также HasB без наследства от HasAB, но это может быть решено с помощью шаблонов и SFINAE.

1
По вопросам рекламы [email protected]