Могу ли я добавить шаблон класса в кортеж?

#c #class #templates #tuples

#c #класс #шаблоны #Кортежи

Вопрос:

Я пытаюсь добавить шаблон класса в tuple

Это мои классы:

 class Parent {
  // ...
}

class Child1 : public Parent {
  // ...
}

class Child2 : public Parent {
  // ...
}
  

Моя цель — добавить класс следующим образом:

 v.push_back({"child1", Child1});
  

чтобы я мог сохранить шаблон класса для создания объекта подобным образом:

 Parent *obj = new v[0][1]();
  

который должен работать следующим образом:

 Parent *obj = new Child1();
  

Я использую это:

 std::vector<std::tuple<std::strin&, template<class T&&t;&&t;&&t; v;
  

чтобы добавить шаблон в кортеж.

Как я могу заставить это работать?

Комментарии:

1. Вы действительно имеете в виду tuple? Похоже на вариант для меня!

2. Я бы сказал, что вы хотите создать шаблон Factory , не так ли? Типы не являются значениями в C , но вы можете попробовать использовать статическую функцию.

3. @Klaus Я должен использовать tuple, потому что там хранятся дополнительные данные

4. @rodri&o Спасибо, я попробую 🙂

Ответ №1:

Нет, вы не можете сохранить тип напрямую. Но вы можете сохранить указатель на функцию, указывающий на функцию, которая создает один из производных классов при вызове.

 std::vector<std::tuple<std::strin&, Parent *(*)()&&t;&&t; v;
v.push_back({"Child1", []() -&&t; Parent * {return new Child1;}});

Parent *ptr = std::&et<1&&t;(v[0])();
  

Здесь Parent *(*)() означает «указатель на функцию без параметров, возвращающий Parent * «.

[]() -&&t; Parent * {return new Child1;} является лямбда-выражением, которое является более или менее анонимной функцией. () указывает на отсутствие параметров и -&&t; Parent * указывает, что возвращаемый тип является Parent * .

Обратите внимание std::&et<1&&t;(...) вместо ...[1] . Последнее не работает с кортежами. Обратите () внимание в конце, который вызывает функцию.

Поскольку ваш кортеж содержит только два элемента, рассмотрите возможность использования std::pair<...&&t; вместо этого. Тогда вы могли бы сделать v[0].second вместо std::&et<1&&t;(v[0]) .

Поскольку вы, похоже, хотите использовать вектор в качестве сопоставления строк с функциями, рассмотрите возможность использования фактического std::map вместо вектора.


Вот полный пример использования std::map :

 #include <iostream&&t;
#include <map&&t;

class Parent
{
  public:
    virtual ~Parent() = default;
    virtual void foo() {std::cout << "Parentn";}
};

class Child1 : public Parent
{
  public:
    void foo() override {std::cout << "Child1n";}
};

class Child2 : public Parent
{
  public:
    void foo() override {std::cout << "Child2n";}
};

int main()
{
    std::map<std::strin&, Parent *(*)()&&t; m;
    m.insert({"Child1", []() -&&t; Parent * {return new Child1;}});

    Parent *ptr = m.at("Child1")();
    ptr-&&t;foo(); // Prints `Child1`.
}
  

Комментарии:

1. Я получил сообщение об ошибке: не удается преобразовать ‘Child1 *’ в ‘Parent *’ в ответ v.push_back({«Child1», []() -&&t; Parent * {вернуть новый Child1;}});

2. @user12175383 Ты забыл наследовать Child от Parent ? Я попытаюсь привести полный пример.

3. @user12175383 Вот так: &cc.&odbolt.or&/z/91n7Px Также я добавил лучший пример (используя std::map ) к самому ответу.

4. Возможное улучшение: верните a std::unique_ptr<Parent&&t; вместо Parent* . Пример: []() -&&t; std::unique_ptr<Parent&&t; { return std::make_unique<Child1&&t;(); } Вам также придется соответствующим образом настроить map .

5. @user12175383 демонстрация использования unique_ptr s вместо этого.