16

I've got a class template, and I need to declare an object of that class, without defining the type parameters, so that I can define them conditionally later, e.g.:

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);
    }
}
Flexo
  • 87,323
  • 22
  • 191
  • 272
user965369
  • 5,413
  • 13
  • 33
  • 47

4 Answers4

9

Well, you certainly can't do that. You'll have to make A derive from another class, for example:

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);
    }
}
Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • Ahh that looks promising, but what exactly happens to the pointer when you assign it to a subclass of that type? Does it (for a better term) cast itself to that type or something...? (as in does it does the memory alloc it points to adjust to meet the memory needed by the subcalss's object?). What are the rules for a base class/sub class relationship – user965369 Oct 16 '11 at 14:34
  • 4
    Exactly. The reason you can't do it like in the OP is that templates are completely expanded at compile time; at run-time, template instances are just regular classes and functions. Their template-based relationship is lost after template expansion. – tdammers Oct 16 '11 at 14:34
  • @user965369: It's basic polymorphism; every instantiation of the templated class A is a subclass of class B, and implicit casting works accordingly. – tdammers Oct 16 '11 at 14:35
  • Ok thanks. Can you suggest any good references to implicit casting, inheritance etc.? – user965369 Oct 16 '11 at 14:37
  • Btw, does that mean because template definition is a run-time feature, memory-wize, you might aswell just define individual classes? It doesn't aid memory consumption? (I know that's not the point of a template but just out of interest). – user965369 Oct 16 '11 at 14:40
  • [The C++ FAQ](http://www.parashift.com/c++-faq-lite/index.html) has plenty of info on inheritance. What do you mean by *"template definition is a run-time feature"*? – Benjamin Lindley Oct 16 '11 at 14:43
  • As in all the neccessary class definitions are generated at compile time, so you might aswell define individual classes? – user965369 Oct 16 '11 at 14:49
  • Also, if you have a base class pointer which points to a subclass, can that pointer access member functions of the subclass it points to? (sorry for all the questions ahah) – user965369 Oct 16 '11 at 14:51
  • 2
    Well, this would require `pure virtual` functions to be usable without any serious brain damage, but is a solution. – pmr Oct 16 '11 at 14:55
  • @pmr could you explain further? – user965369 Oct 16 '11 at 15:02
  • 1
    @user965369: Time to open up [your C++ book](http://jcatki.no-ip.org/fncpp/Resources). SO is not for iterative tuition... or any other kind of tuition, really. – Lightness Races in Orbit Oct 16 '11 at 15:21
  • 2
    It would be better to use virtual destructor for base class IMHO. – bartolo-otrit May 29 '13 at 13:24
4

The easiest way to do this is to use another function.

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));
}

This maintains all type information and does not depend on inheritance. The disadvantage of inheritance is that T cannot appear in any function interfaces, but with this situation it can.

Puppy
  • 144,682
  • 38
  • 256
  • 465
3

Templates are expanded at compile-time, so your problem is really just the same as the following:

struct A_float {            // struct is easier when everything's 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);
}

Hopefully if you saw the above code, you'd think (as well as "maybe I should be using templates") "I am going to need a common base class for this, or else I'll refactor".

When you generate the two types at compile-time using a class template, this conclusion is the same.

  • I'd recommend the refactoring, going for a solution like Puppy's; creating an inheritance hierarchy just to work around a program logic flow flaw is programming backwards!
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
-1

You can use void pointer while create object of class A
Look at Following code sample :

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;    
    }
}
Mahesh Meniya
  • 2,627
  • 3
  • 18
  • 17