Можно ли определить список очередей, где каждая очередь может быть разных типов? - PullRequest
0 голосов
/ 10 июля 2019

Я пытаюсь определить класс, где основным элементом является список очередей.

Проблема в том, что каждая очередь может быть разных типов.

Вот пример того, что я хотел бы получить. Если мы определим эти очереди:

queue1 (type int)    = {5,7,3,4,5}
queue2 (type string) = {"Sam","Peter"}
queue3 (type string) = {"January","February","March"}
queue4 (type int)    = {10}

Тогда я хотел бы иметь возможность создавать объекты, подобные этим:

object1.list_of_queues = {queue1,queue2}
object2.list_of_queues = {queue2,queue3,queue4}

Все они основаны на одном классе.

Я могу создать тип "список очередей", но все они имеют один и тот же тип:

typedef std::queue<std::string> queue_type; //queue of strings
typedef std::list<queue_type> list_type;    //list of queues of (only) strings

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

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 10 июля 2019

Можно ли определить список очередей, в которых каждая очередь может быть разных типов?

Не напрямую.

A std::queue одного типа элементаэто тип, отличный от очереди другого типа элемента.std::list является однородным контейнером: все элементы имеют одинаковый тип.

То, что вы можете сделать, - это иметь список или очередь оболочки, удаляющей тип, такой как std::variant или std::any, которая может содержать объектытипа из соответственно ограниченного или неограниченного выбора.

1 голос
/ 10 июля 2019

Да, есть способы сделать это. Это утилиты как во время выполнения, так и во время компиляции. Мои любимые утилиты следующих типов. C ++ подобен псевдокоду:

#include <typeinfo>

namespace dynamics {

class AnyBase {
     virtual const type_info& getTypeInfo();
     virtual ~AnyBase()
}

template<typename T>
class DynamicAny : public AnyBase {
     type_info typekind;
     T val;

     template<typename T>
     DynamicAny(const T& t) : typekind(typeof(T)), val(t) {}

     //... usual move/copy constructors/operators follow

     //conversion operators
     inline operator T&() {
          return val;
     }
     inline operator const T&() const {
          return val;
     }

     //possibly comparison operators with const T& too...

     //virtual call for type information for this type
     const type_info& getTypeInfo() {
           return typekind;
     }
}

}

Затем вы можете включить любой std::unique_ptr<AnyBase> в вектор или очередь или любую структуру данных по этому вопросу. Но присвойте ему DynamicAny<T> желаемого типа. Затем, когда вы получите его из этой структуры данных, просто вызовите getTypeInfo() на AnyBase, чтобы определить, к какому DynamicAny<T> привести его. Смотрите type_info для более подробной информации. http://www.cplusplus.com/reference/typeinfo/type_info/

Вы также можете использовать std::any, который делает то же самое. https://en.cppreference.com/w/cpp/utility/any c ++ 17 и далее.

typedef std::queue<std::unique_ptr<AnyBase>> queue_type; //queue of unique_ptr of DynamicAny<T>
typedef std::list<queue_type> list_type;    //list of queues of (only) strings
1 голос
/ 10 июля 2019

Основываясь на ваших комментариях, я подозреваю, что вы хотите сделать что-то подобное:

#include <iostream>
#include <string>
#include <list>
#include <memory>

class Shape
{
public:
    virtual double area() const = 0;
};


class Circle : public Shape
{
    double radius;
public:
    Circle(const double r) : radius(r) {}
    double area() const {
        return 3.1416 * radius * radius;
    }
};


class Square : public Shape
{
    double side;
public:
    Square(const double s) : side(s) {}
    double area() const {
        return side * side;
    }
};


int main()
{
    std::list<std::unique_ptr<Shape>> my_list;
    my_list.push_back(std::make_unique<Circle>(2.0));
    my_list.push_back(std::make_unique<Square>(4.0));

    for(const auto& el : my_list)
        std::cout << el->area() << std::endl;
}

Где я использовал полиморфизм / наследование для создания объекта типа Shape.Затем я использую список этого родительского объекта как pointer, чтобы можно было создавать различные дочерние элементы, такие как Cirlce или Square.

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