Задать вопрос
@Acaunt

Возможно ли как-то обойти ограничение на невозможность создать виртуальный шаблонный метод?

Вот абстрактный пример кода, в котором нужно сделать так чтобы метод print мог принимать любой тип:
#include <iostream>
#include <memory>

struct Base {
    virtual void print(const int&) = 0;
};

struct No_work : Base {
    void print(const int&) override {
        // метод который ничего не делает
    }
};

struct Work : Base {
    int end;
    
    Work(const int& end) : end(end) {}
    
    void print(const int& info) override {
        // метод который что-то делает
        for (int i = 0; i < end; ++i) {
            std::cout << info << std::endl;
        }
    }
};

int main() {
    std::unique_ptr<Base> printer = std::make_unique<Work>(5);
    
    printer->print(5);
    
    printer = std::make_unique<No_work>();
    
    printer->print(6);
    
    printer = std::make_unique<Work>(2);
    
    printer->print(7);
    
    return 0;
}


Хочется добиться подобного поведения в коде, так чтобы в зависимости от условия код мог выполняться, а мог пропускаться и к тому же не выделять лишнюю не используемую память.
  • Вопрос задан
  • 61 просмотр
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 2
@Mercury13
Программист на «си с крестами» и не только
Плавали, знаем.
Самый простой способ, когда не нужно вписывать новые типы, вот.
class Base {
public:
    // Что нужно реализовать
    virtual void doPrint(std::string_view) = 0;
    virtual bool isActive() const = 0;

    // морда лица
    template<class... Args>
    void print(Args&&... args);
protected:
   // разные там преобразователи-писатели
   void printOne(int);
   void printOne(std::string_view x) { doPrint(x); }
   ...
};

template<class... Args>
void Base::print(Args&&... args)
{
  if (isActive()) {  // Проверка на активность
     (..., printOne(std::forward<Args>(args)));  // Преобразование и вывод
  }
}

void Base::printOne(int x)
{
   char buf[20];
   auto r = std::to_chars(std::begin(buf), std::end(buf), x);
   doPrint(std::string_view{ std::begin(buf), r.ptr });
}
Ответ написан
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Зачем вам делать виртуальный метод в шаблоне, если вы в шаблоне же определяете, должен ли он что-то делать или нет? Вы можете сделать 2 разных инстанса шаблона: один с функцией, которая что-то делает, и другой, где - ничего не делает. Виртуальность тут не дает никаких дополнительных степеней свободы.

Если вам надо как-то дополнительно отключить определенную функциональность уже существующего класса, то надо или делать невиртуальную функцию в шаблоне, которая будет вызывать виртуальную фнукцию из потомка (или пропускать вызов), или в функциях потомка проверять какой-то IsActive(), определенный в шаблоне.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы