Как передать параметр типа шаблона

#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()
{
}