Динамическое создание шаблона

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

template<typename T>
class A{
public:
    A(T v){var = v};
    ~A(){};

    T var;
}

int main(){
    A<>* object; // Or sometihng along these lines...?
    if(/* something*/)
        object = new A<float>(0.2f);
    else{
        object = new A<int>(3);
    }
}

Ответ 1

Ну, вы, конечно, не можете этого сделать. Вам нужно сделать вывод A из другого класса, например:

template<typename T>
class A : public B {
public:
    A(T v){var = v};
    ~A(){};

    T var;
}

int main(){
    B* object;
    if(/* something*/)
        object = new A<float>(0.2f);
    else{
        object = new A<int>(3);
    }
}

Ответ 2

Самый простой способ сделать это - использовать другую функцию.

template<typename T> void other_stuff(A<T>* object) {
    // use T here
}
int main() {
    if (condition)
        other_stuff(new A<float>(0.2f));
    else
        other_stuff(new A<int>(3));
}

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

Ответ 3

Шаблоны раскрываются во время компиляции, поэтому ваша проблема на самом деле такая же, как показано ниже:

struct A_float {            // struct is easier when everything public
    A(float v) : var(v) {}  // (use the ctor-initializer please!)
    ~A() {}

    float var;
};                          // don't forget the semicolon

struct A_int {
    A(int v) : var(v) {}
    ~A() {}

    int var;
};

int main() {
    WhatType* object; // What type here?
    if (/* something*/)
        object = new A_float(0.2f);
    else
        object = new A_int(3);
}

Надеюсь, если вы увидели приведенный выше код, вы бы подумали (а также "возможно, мне следует использовать шаблоны") "Мне понадобится общий базовый класс для этого, иначе я буду рефакторинг".

Когда вы генерируете два типа во время компиляции, используя шаблон класса, этот вывод один и тот же.

  • Я бы порекомендовал рефакторинг, выбрав решение, подобное Puppy; создание иерархии наследования просто для обхода недостатка логического потока программы - это программирование в обратном направлении!

Ответ 4

Вы можете использовать указатель void при создании объекта класса A
Посмотрите следующий образец кода:

template<typename T>
class A
{
 public:
    A(T v){var = v;};
    A(){};
    ~A(){};
    T var;
};
int main(){
    A<void *> object; 
    if(1){ // do this
        object = new A<float>(0.31f);
        // type cast void pointer to get value
        cout<<*(float*)object.var;    
    }
    else{ // else do this
        object = new A<int>(34);
        // type cast void pointer to get value
        cout<<*(int*)object.var;    
    }
}