Как я должен хранить шаблонные функции в любом контейнере? - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть шаблонный класс Prob, который служит способом организации различных задач программирования из разных наборов задач.Шаблон - это номер проблемы.Как бы я занялся хранением различных объектов Prob в векторе или на карте?

Вот объявление класса:

template<int ProbNum>
class Prob 
{
    std::string 
    text(std::ostream& out) 
    {
        out << "Prob" << ((ProbNum < 10) ? "0" : "") << ProbNum << ": "; 
    }

    void solve(std::ostream& out);
};

Другими словами, если я хочу объявить объект для задачи 1для некоторого набора проблем я бы сделал

Prob<1> p1;

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

Редактировать: я хочу использовать этот класс в качестве абстрактного класса для других классов Проб.

Редактировать2: добавлено больше кода для пояснения.

Редактировать3: Верхняя половина - это Проб1.hpp

Нижняя половина - это файл драйвера о том, как я хочу его использовать.

#include <iostream>

#include "Prob.hpp"

template<>
void
Prob<1>::solve(std::ostream& out)
{
    out << "solution to prob1";
}

/***************************************************/

#include <iostream>
#include <cstdlib>

#include "Prob.hpp"

// Finished Problems
#include "Prob1.hpp"

int
main(int argc, char* argv[])
{
    Prob<1> p;
    p.solve(std::cout);
}

1 Ответ

0 голосов
/ 30 ноября 2018

Каждый экземпляр класса шаблона представляет собой отдельный тип.Следовательно, контейнеры типа std::vector не могут содержать Prob<ProbNum> для различных значений ProbNum.Если вы знаете во время компиляции нужное количество Prob<ProbNum> экземпляров и соответствующие значения параметра шаблона int ProbNum, вы можете сохранить все в tuple.Например:

auto mycollection = std::make_tuple(Prob<1>(), Prob<2>());

Более общим решением может быть определение абстрактного базового класса для Prob.Тогда вам удастся сохранить вектор объектов Prob<ProbNum> с неоднородными значениями int ProbNum, если вы определите вектор указателей на базовый класс.Чтобы это работало, вы должны предоставить интерфейс в базовом классе, т. Е. Каждый член Prob<ProbNum>, к которому вы хотите получить доступ через vector базового класса, должен быть virtual и уже объявлен в базовом классе.

Рассмотрим следующий пример:

#include <iostream>
#include <memory>
#include <vector>

struct base {
  virtual void print() const = 0;
  virtual ~base() = default;
};

template <int i>
struct derived : public base
{
  virtual void print() const { std::cout << i << std::endl; }
};

int main()
{
  std::vector<std::unique_ptr<base>> vec;
  vec.emplace_back(new derived<1>());
  vec.emplace_back(new derived<3>());
  vec.emplace_back(new derived<5>());
  for (auto& el : vec)
    el->print();

  return 0;  
}

Переменная vec по сути является вектором указателей на объекты типа derived<i> с неоднородными значениями i.Поскольку base::print() является виртуальным, он правильно разрешается в соответствующий метод класса derived<i>.Обратите внимание, что я использовал умный указатель , чтобы избежать утечки памяти.

Также важно объявить virtual деструктором base, см. Обсуждение Почему я долженобъявить виртуальный деструктор для абстрактного класса в C ++? .

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