#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 вместо этого.