Специализация шаблона не соответствует производному классу - PullRequest
0 голосов
/ 13 января 2020

У меня есть класс Textf, который может хранить форматированный текст и его свойства (сейчас это только цвет). Затем у меня есть класс Header, который наследуется от него и добавляет пунктирное подчеркивание, имеет некоторые дополнительные атрибуты и т. Д. c.

Кроме того, у меня есть отдельный класс println (используется класс для поддержки частичной специализации). Среди других типов я добавил поддержку Textf объектов. Естественно, я предположил (как и в случае с функциями), что компилятор будет сопоставлять объект Header с шаблоном Textf. Вместо этого я получил ошибку MSV C C2679 (с использованием VS 2019), которая вызвана тем, что компилятор по умолчанию установил исходное определение шаблона (поскольку шаблон Textf не был сопоставлен, поскольку объект является Header объектом).

Если бы я определил другую специализацию шаблона для каждого дочернего класса, обе специализации имели бы одинаковое поведение, делая код чрезвычайно избыточным (особенно если было много дочерних объектов).

Для ясности, Вот пример кода:

template<class LnTy>
class println  // Default template def
{
public:
    println(LnTy line)
    {
        std::cout << line;
    }
};

class Textf
{
protected:
    std::string_view m_text;
    Color m_text_color;  // Color is a scoped enum
    Color m_background_color;

public:
    // Constructors, etc...

    virtual void display() const
    {
        // Change color
        // Diplay text
        // Restore color
    }
};

class Header : public Textf
{
private:
    // 'U_COORD' is struct { unsigned X, Y; }
    U_COORD m_text_start_location;

public:
   // Constructors, etc...

    void display() const override
    {
        // Change color
        // Change cursor location
        // Display text
        // Display dashed underline (next line)
        // Restore cursor location (next line)
        // Restore color
    }
};

template<>
class println<Textf>  // Specialization for 'Textf'
{
    println(Textf line)
    {
        line.display();
    }
};

Как использовать преимущества полиморфизма в шаблонах для такой ситуации?

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

В случае, если это помогает, я использую консоль Windows API для изменения цвета текста.

Ответы [ 2 ]

3 голосов
/ 13 января 2020

Вы можете использовать SFINAE, чтобы убедиться, что используется правильная версия шаблона.

template<class LnTy, class = void> // second parameter is used in the specialization for SFINAE
class println  // Default template def
{
public:
    println(const LnTy& line)
    {
        std::cout << line;
    }
};

template<class LnTy>
class println<LnTy, std::enable_if_t<std::is_base_of_v<Textf, LnTy>>>
{
    println(const Textf& line)
    {
        line.display();
    }
};

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

template<class LnTy, std::enable_if_t<!std::is_base_of_v<Textf, LnTy>, int> = 0>
void println(const LnTy& line)
{
    std::cout << line;
}

template<class LnTy, std::enable_if_t<std::is_base_of_v<Textf, LnTy>, int> = 0>
void println(const Textf& line)
{
    line.display();
}
0 голосов
/ 13 января 2020

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

template<class LnTy>
typename std::enable_if< !std::is_base_of<Textf, LnTy>::value >::type
class println  // Default template def
{
public:
    println(LnTy line)
    {
        std::cout << line;
    }
}

и сделать "специализированную" версию перегруженной без шаблона.

...