Задание 5 (индивидуальное): метавычисления типов

Указания:

  • Для реализации этого задания необходимо использовать библиотеку MPL.
  • Задание необходимо выполнить в виде метафункции, принимающей входные данные в виде параметров (контейнеров MPL там, где требуется переменное количество типов).

  1. Дана последовательность типов. Разделить её на две последовательности: одна должна состоять из базовых классов, вторая — из производных от них, стоящих на тех же позициях. Если это сделать невозможно, вывести сообщение об ошибке времени компиляции. Для первой последовательности сгенерировать интерфейс абстрактной фабрики, для второй — конкретной, создающей объекты в динамической памяти при помощи конструирования по умолчанию. Проверить работоспособность фабрики можно на следующем коде:

    #define ABSTRACT(class) \
      struct Abstract ## class \
      { \
        virtual ~Abstract ## class() {} \
        virtual void print() = 0; \
      }; \
      \
      struct class : public Abstract ## class \
      { \
        virtual void print() override \
        { \
          cout << #class << endl; \
        } \
      };
    
    ABSTRACT(C1);
    ABSTRACT(C2);
    ABSTRACT(C3);
    
    typedef mpl::vector <C3, AbstractC1, AbstractC2, C1, AbstractC3, C2> Types;
    typedef factory <Types>::type FactoryPair;
    typedef FactoryPair::first AbstractFactory;
    typedef FactoryPair::second ConcreteFactory;
    
    void makeObjects(AbstractFactory &rFactory)
    {
      AbstractC1 *pC1 = rFactory.create <AbstractC1> ();
      AbstractC2 *pC2 = rFactory.create <AbstractC2> ();
      AbstractC3 *pC3 = rFactory.create <AbstractC3> ();
      pC1->print();
      pC2->print();
      pC3->print();
      delete pC1;
      delete pC2;
      delete pC3;
    }
    
    int main()
    {
      ConcreteFactory factory;
      makeObjects(factory);
    }
    
  2. Дана последовательность типов. Проверить, что все они являются объектными, найти максимальный размер среди них. Сгенерировать класс «интеллектуальное объединение», хранящий значение одного из перечисленных типов в области динамической памяти размера, достаточного для хранения максимального по размеру типа. Предусмотреть в классе конструктор, инициализирующий заданное значение, деструктор, операции получения и установки значения, семантику копирования и перемещения. Проверить работоспособность класса можно на следующем коде:

    struct Test
    {
      int m_n;
      Test() : m_n(99) { cout << "Test()" << endl; }
      Test(const Test &rcT) : m_n(rcT.m_n) { cout << "Test(const Test &)" << endl; }
      ~Test() { cout << "~Test()" << endl; }
    };
    
    int main()
    {
      typedef mpl::vector <int, float [10], std::string, Test> types;
      Test t;
      smart_union <types> u1(t);
      cout << u1.get <Test> ().m_n << endl;
      u1.set <std::string> ("abc");
      cout << u1.get <std::string> () << endl;
    }
    
  3. Дана последовательность типов. Проверить, что все они являются классами и упорядочить их так, чтобы производные классы находились раньше их базовых. Для полученной последовательности проверить, что все классы являются производными от последнего, и сгенерировать симметричный двойной линейный диспетчер.

  4. Дана последовательность типов. Проверить, что все они являются классами и упорядочить их так, чтобы производные классы находились раньше их базовых. Для полученной последовательности проверить, что все классы являются производными от последнего, и сгенерировать симметричный тройной линейный диспетчер.

  5. Дана последовательность типов. Проверить, что все они являются классами и удалить из них дубликаты. Для полученной последовательности сгенерировать циклический посетитель.

  6. Дана последовательность типов. Проверить, что все они являются классами и удалить из них дубликаты. Для полученной последовательности сгенерировать ациклический посетитель.