#c #templates
#c #шаблоны
Вопрос:
У меня была дискуссия с коллегой о шаблонах, и одна из вещей, о которых мы говорили, заключается в том, что, учитывая такой класс, как следующий, как бы вам сошло с рук использование инструкции switch с помощью шаблонов?
enum EVersion
{
Version_1,
Version_2,
};
class CBar
{
...
public:
EVersion ver;
};
class CFoo
{
void Reset()
{
switch (pBar->ver)
{
case Version_1:
TemplateHelperMethod<Version_1>::DoSomething();
break;
case Version_2:
TemplateHelperMethod<Version_2>::DoSomething();
break;
}
}
CBar *pBar;
};
CFoo* pFoo = new CFoo(pBar);
pFoo->Reset();
Одним из решений является создание производного шаблонного класса и перемещение функции в производный класс, который должен использовать оператор switch на основе версии.
class CFoo
{
...
CBar *pBar;
};
template <EVersion Ver>
class CFoo2 : public Foo
{
void Reset()
{
TemplateHelperMethod<Ver>::DoSomething();
}
};
CFoo2<Version_2>* pFoo = new CFoo2<Version_2>(pBar);
pFoo->Reset();
Однако мой коллега предположил, что можно сохранить исходную функцию в базовом классе и просто изменить ее на шаблонный метод (что-то вроде приведенного ниже). Тем не менее, я немного не понимаю, как это будет работать. Как бы вы использовали производный класс для передачи типа шаблонному методу сейчас? Если у кого-нибудь есть какие-либо идеи, пожалуйста, дайте мне знать. Спасибо.
class CFoo
{
template <EVersion Ver>
void Reset()
{
TemplateHelperMethod<Ver>::DoSomething();
}
CBar *pBar;
};
template <EVersion Ver>
class CFoo2 : public Foo
{
// does anything go here?
};
CFoo2<Version_2>* pFoo = new CFoo2<Version_2>(pBar);
pFoo->Reset();
OR
CFoo* pFoo = new CFoo(pBar);
// Can you do this? since CFoo2 derives from CFoo
// and has no additional members...
CFoo2<Version_2>* pFoo2 = static_cast<CFoo2<Version_2>*>(pFoo);
pFoo2->Reset();
Комментарии:
1. Это добавило бы значительного кислорода в огонь вашего вопроса, если бы опубликованные примеры кода имели шанс на компиляцию . Похоже , что вы пытаетесь использовать отправку тегов, но это трудно определить.
2. Прочитайте здесь и попробуйте. cprogramming.com/tutorial/templated_functions.html
Ответ №1:
Я думаю, что то, что предложил ваш коллега, невозможно, поскольку pBar->ver
не является константой времени компиляции. Вы не можете использовать его в качестве параметра шаблона.
Правильным решением для удаления переключателя в переменной среды выполнения является полиморфизм во время выполнения
struct Version
{
virtual ~Version() = default;
virtual void DoSomething() = 0;
};
class CBar
{
public:
Versionamp; ver;
};
class CFoo
{
public:
void Reset()
{
pBar->ver.DoSomething();
}
CBar *pBar;
};
Если вы создадите CBar::ver
константу времени компиляции, вы можете использовать ее для специализации CFoo
на ней.
template<EVersion Version>
struct CBar
{
EVersion version = Version;
};
template<EVersion Version>
struct CFoo
{
void Reset();
CBar<Version> pBar;
};
template<>
void CFoo<Version_1>::Reset()
{
}
template<>
void CFoo<Version_2>::Reset()
{
}