Как проверить типы в шаблонном классе в c ++? - PullRequest
0 голосов
/ 01 мая 2020

У меня есть класс Button, который может отображать изображение или строку текста, которые я пытаюсь использовать для реализации шаблона.

Если это текст, то тип шаблона: const char *

Если это изображение, то тип шаблона: const wchar_t *

Вот метод, который должен различать два типа:

template <typename T>
void Button<T>::draw(EasyGraphics* canvas)
{
    canvas->setBackColour(colour);

    if (mouseOver)
    {
        canvas->setPenColour(EasyGraphics::BLACK, 4);
    }
    else
    {
        canvas->setPenColour(EasyGraphics::BLACK, 2);
    }

    canvas->drawRectangle(Entity::GetX(), Entity::GetY(), Entity::getWidth(), Entity::getHeight(), true);
    canvas->setFont(20, L"");
    canvas->setTextColour(textColour);

    switch (typeid(T))
    {
        // Button has display text
        case typeid(const char*):
        {
            canvas->drawText(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3);
            break;
        }
        // Button has display image
        case typeid(const wchar_t*):
        {
            canvas->drawBitmap(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3, 60, 60, 0x0000FF00);
            break;
        }
    }
}

Мне кажется, что чтобы выключатель внизу работал правильно. Я не уверен, является ли переключатель лучшим способом go. Любой совет будет оценен, ура.

Ответы [ 2 ]

3 голосов
/ 01 мая 2020

Используйте типовые черты (и if constexpr) вместо typeid. Например:

void g_char(const char*);
void g_wchar_t(const wchar_t*);

template <typename T>
void f(T)
{
    if constexpr (std::is_same_v<T, const char*>)
    {
        g_char(T());
    }
    else if constexpr (std::is_same_v<T, const wchar_t*>)
    {
        g_wchar_t(T());
    }
}

http://coliru.stacked-crooked.com/a/08e9e66ed5c776a4

Причина, по которой переключатель здесь не работает, заключается в том, что условие должно быть неявно преобразовано в целочисленный тип, и std::type_info (что возвращает typeid) не так.

Но тогда, если вы попытаетесь сохранить выражения typeid, у вас возникнет проблема проверки типов во время компиляции при попытке вызвать drawText или drawBitmap. Оба вызова должны быть действительными, если вы не используете филиалы constexpr (if constexpr). Однако в этом случае условия должны быть константами времени компиляции, где typeid нельзя использовать. Таким образом, вместо этого вы можете использовать черты типа, в частности, std::is_same.

1 голос
/ 01 мая 2020

Проведите специализацию шаблона:

template <typename T>
void DoDraw(EasyGraphics* canvas);

template<>
void DoDraw<char>(EasyGraphics* canvas)
{
  canvas->drawText(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3);
}

template<>
void DoDraw<wchar_t>(EasyGraphics* canvas)
{
  canvas->drawBitmap(displayData, Entity::GetX() + textXOfset, Entity::GetY() + (Entity::getHeight() / 4) - 3, 60, 60, 0x0000FF00);
}

template <typename T>
void Button<T>::draw(EasyGraphics* canvas)
{
  ...
  DoDraw(canvas);
}

* проверьте аргумент шаблона, довольно странно иметь const char*, а не просто char.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...