#include <iostream>
#include <fstream>
template <unsigned int dim>
class MyClass
{
public:
private:
double data[dim];
//many more members that depend on dim
};
int main()
{
std::fstream myfile("path_to_my_file.txt", std::ios_base::in);
unsigned int dim;
myfile >> dim; //depending on the file content, dim=1 or dim=2
std::shared_ptr<MyClass<dim>> ptr;
}
У меня есть указатель на класс с параметром шаблона dim
(целое число)
В моем случае dim
это либо 1
, либо 2
.
Я знаю, что параметры шаблона должны быть известны во время компиляции. Но есть ли способ сказать компилятору скомпилировать и MyClass<1>
, и MyClass<2>
и выбрать нужный класс во время выполнения?
Шаблоны не имеют отношения к проблеме. Вы ищете фабричную функцию, или полиморфизм, или и то, и другое.
@NathanPierson Как это может выглядеть при использовании std::variant?
Да, используйте оператор if. На самом деле не вижу проблемы, хотя, возможно, реальная проблема не указана.
@john Проблема в том, что я читаю dim из файла во время выполнения.
В некоторых сценариях вы можете захотеть, чтобы ваш класс шаблона расширял некоторый базовый тип с помощью виртуального деструктора (и, возможно, некоторых виртуальных функций) и использовал std::shared_ptr<my_class_base>
, но, не зная деталей my_class
или того, как он используется, мы не сможем дать хороший совет. здесь...
@Simon Но оператор if может принять решение на основе значения, считанного из файла во время выполнения. Я предполагаю, что ваш реальный вопрос заключается в том, что после того, как вы создали объект с соответствующим измерением, вы затем обрабатываете этот объект с тем же кодом, как если бы вы создали другой объект. Это вопрос, на который трудно ответить без дополнительного контекста,
@john Я предоставил минимальный пример, который примерно иллюстрирует то, что я хочу сделать.
@Jason Джейсон Вы указали на std::variant. Уместно ли это в моем сценарии? (см. обновленный вопрос)
@Simon, вашему примеру все еще не хватает использования. Например, он не дает примера того, как выглядит клиентский код. На что похож код, использующий MyClass
?
Вашего примера недостаточно, чтобы дать правильный ответ. Если нет предположений о my_class<t>
, std::shared_ptr<my_class<1>>
и std::shared_ptr<my_class<2>>
— совершенно несвязанные типы, поэтому, если ваша цель — написать что-то вроде:
int Dim;
... // set Dim at runtime
std::shared_ptr<my_class<Dim>> p;
тогда вам нужно будет использовать союзный тип (например, простой union
или std::variant
или что-то еще), что, ИМХО, не очень хорошая идея.
Другой вариант использования, который я могу себе представить, заключается в том, что вы будете вызывать функцию шаблона, созданную с желаемым типом. В этом случае вы можете написать простой switch
.
Вот минимальный пример:
template<typename T> void foo();
...
int Dim;
...
switch (Dim)
{
case 1:
{
foo<std::shared_ptr<my_class<1>>();
break;
}
case 2:
{
foo<std::shared_ptr<my_class<2>>();
break;
}
}
Итак, на вопрос все еще трудно ответить, но я представлю возможное решение, основанное на полиморфизме. Решение на основе шаблона также может быть возможным, но выбор между этими двумя решениями затруднен из-за отсутствия контекста.
class Base
{
public:
virtual ~Base() {};
virtual void something() = 0;
// more pure virtual methods
};
template <unsigned int dim>
class MyClass : public Base
{
public:
void something() override;
// overrides for other pure virtual methods
private:
double data[dim];
//many more members that depend on dim
};
int main()
{
int dim = ,,,;
shared_ptr<Base> ptr;
if (dim == 1)
ptr = make_shared<MyClass<1>>();
else
ptr = make_shared<MyClass<2>>();
ptr->something();
}
Спасибо. Я попробую. Не могли бы вы показать, как использовать std::variant? Потому что MyClass на самом деле является каким-то независимым классом, и на самом деле нет необходимости связывать с ним базовый класс.
Учебник о том, как использовать std::variant
, немного выше моего понимания. Я думаю, вы можете найти что-то в Интернете.
Как это например.
Я пока не видел std::variant в этом контексте. Если бы это не имело для вас большого значения, я был бы признателен, если бы вы расширили свой ответ.
std::variant<std::shared_ptr<MyClass<1>>, std::shared_ptr<MyClass<2>>> ptr;
. В какой-то момент вам придется научиться исследовать вещи самостоятельно, вместо того, чтобы вам их показывали. Сейчас вроде хорошее время..
Ты прав. Я должен попытаться справиться с этим сам. Спасибо!
Чтобы получить используемый вариант с помощью ptr, std::get<0>(ptr) и std::get<1>(ptr) отлично работают. Проблема в том, что я должен обернуть это в оператор if, поскольку ptr.index() не является константой времени компиляции, поэтому std::get<ptr.index()>(ptr) явно не работает. Есть ли способ получить индекс без использования std::get?
Я подумал, что лучше задать это в новом вопросе stackoverflow.com/questions/76074067/…
Покажите нам минимальный воспроизводимый пример . Также см. C++ std::variant vs std::any