Параметр шаблона (1 или 2): любой способ установить его во время выполнения (время компиляции, если,...)?

#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> и выбрать нужный класс во время выполнения?

std::variant?
Nathan Pierson 20.04.2023 17:20

Шаблоны не имеют отношения к проблеме. Вы ищете фабричную функцию, или полиморфизм, или и то, и другое.

Captain Giraffe 20.04.2023 17:23

@NathanPierson Как это может выглядеть при использовании std::variant?

Simon 20.04.2023 17:23

Да, используйте оператор if. На самом деле не вижу проблемы, хотя, возможно, реальная проблема не указана.

john 20.04.2023 17:39

@john Проблема в том, что я читаю dim из файла во время выполнения.

Simon 20.04.2023 17:49

В некоторых сценариях вы можете захотеть, чтобы ваш класс шаблона расширял некоторый базовый тип с помощью виртуального деструктора (и, возможно, некоторых виртуальных функций) и использовал std::shared_ptr<my_class_base>, но, не зная деталей my_class или того, как он используется, мы не сможем дать хороший совет. здесь...

fabian 20.04.2023 19:25

@Simon Но оператор if может принять решение на основе значения, считанного из файла во время выполнения. Я предполагаю, что ваш реальный вопрос заключается в том, что после того, как вы создали объект с соответствующим измерением, вы затем обрабатываете этот объект с тем же кодом, как если бы вы создали другой объект. Это вопрос, на который трудно ответить без дополнительного контекста,

john 20.04.2023 19:34

@john Я предоставил минимальный пример, который примерно иллюстрирует то, что я хочу сделать.

Simon 20.04.2023 22:09

@Jason Джейсон Вы указали на std::variant. Уместно ли это в моем сценарии? (см. обновленный вопрос)

Simon 20.04.2023 22:24

@Simon, вашему примеру все еще не хватает использования. Например, он не дает примера того, как выглядит клиентский код. На что похож код, использующий MyClass?

Enlico 21.04.2023 09:20
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
11
76
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вашего примера недостаточно, чтобы дать правильный ответ. Если нет предположений о 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 на самом деле является каким-то независимым классом, и на самом деле нет необходимости связывать с ним базовый класс.

Simon 21.04.2023 09:17

Учебник о том, как использовать std::variant, немного выше моего понимания. Я думаю, вы можете найти что-то в Интернете.

john 21.04.2023 09:23

Как это например.

john 21.04.2023 09:25

Я пока не видел std::variant в этом контексте. Если бы это не имело для вас большого значения, я был бы признателен, если бы вы расширили свой ответ.

Simon 21.04.2023 09:25
std::variant<std::shared_ptr<MyClass<1>>, std::shared_ptr<MyClass<2>>> ptr;. В какой-то момент вам придется научиться исследовать вещи самостоятельно, вместо того, чтобы вам их показывали. Сейчас вроде хорошее время..
john 21.04.2023 09:28

Ты прав. Я должен попытаться справиться с этим сам. Спасибо!

Simon 21.04.2023 09:40

Чтобы получить используемый вариант с помощью ptr, std::get<0>(ptr) и std::get<1>(ptr) отлично работают. Проблема в том, что я должен обернуть это в оператор if, поскольку ptr.index() не является константой времени компиляции, поэтому std::get<ptr.index()>(ptr) явно не работает. Есть ли способ получить индекс без использования std::get?

Simon 21.04.2023 16:08

Я подумал, что лучше задать это в новом вопросе stackoverflow.com/questions/76074067/…

Simon 21.04.2023 16:25

Другие вопросы по теме