-1

I have a template class that get two template arguments.

template <class T,class A>
class Z{...};

Say I have four types of T, and same amount for A. So, there are 16 options!

If I want to choose one of them at runtime, I need to write a huge and disgusting case.

I know that C++ doesn't support runtime templates.

Is there another way to do it?

Kara
  • 6,115
  • 16
  • 50
  • 57
yoni
  • 1,164
  • 2
  • 13
  • 29
  • 4
    Depends very much on what you need the template to do. Obviously, you won't get metaprogramming at runtime. But simple polymorphism may be sufficent for your case. –  Dec 18 '11 at 19:12
  • 1
    I am thinking a factory function returning a shared_ptr to an interface would work perfectly for this. –  Dec 18 '11 at 19:13
  • @delnan and Ethan, I want to understand your suggestions. Please write it in the answers with details. thank you. – yoni Dec 18 '11 at 19:17
  • 1
    Please describe the problem you are trying to solve, rather your attempt to solve it with templates. – curiousguy Dec 18 '11 at 19:44
  • 1
    I don't understand the down votes on this question. @yoni acknowledges that there is no support for runtime templates and is asking about a workaround. – mantler Dec 18 '11 at 20:28

5 Answers5

3

No, there really isn't. It's inherent in the nature of templates that this is completely and totally impossible.

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

A way to achieve something kind of similar is to add dependencies to class Z and provide these at runtime -- which is known as the Strategy pattern.

Of course this means that class Z is no longer templated with all that this entails. But there's really no way to have your pie and eat it too: templates are a compile-time construct, while you are asking about ways to configure something at runtime. You cannot configure a type at runtime, only an object.

Jon
  • 428,835
  • 81
  • 738
  • 806
0

I'm not saying that this is a good solution but I've seen it implemented in the past: you could keep the code for your templated class around in a resource file and compile it at runtime into a pluggable module!

By the way, I would suggest to refactor the problem so that instead of instantiating MN templates you only need M + N; I don't know it this is possible in your problem but it usually is, e.g. if you are translating from a type to another, it's usually possible to introduce an intermediate representation that works for all types. You still need either a case or a form of polymorphism to handle the various type though, but that's kind of inevitable.

UncleZeiv
  • 18,272
  • 7
  • 49
  • 77
0

Virtual Classes gives you at runtime what templates give you at compile time .. kind of.

Template code when written is not real code, just a template that can be used to generate code. Every time you use it .. it'll usually generate the code right there. eg.

Z<int, std::string> z; // At this point a new class called Z<int, std::string> is defined, then the code to instantiate it at run time is generated.

This might be a useful read: c++ standard practice: virtual interface classes vs. templates

Maybe this is what you're after ? The similar sort of thing using polymorphism and virtual classes ..

class Z{
public:
    virtual void doSomething();
};

class ZT : public Z {
public:
    void doSomething();
};

class ZA : public Z {
public:
    void doSomething();
};

...

void useClasses(Z* ptr) {
    ZT* ztPtr = dynamic_cast<ZT*>(ptr); // Runtime conversion
    if (ztPtr) {
         // do specific stuff for this type
    } else {
         ptr->doSomething(); // generic behaviour that'll call whichever class ptr actually is
    }
}
Community
  • 1
  • 1
matiu
  • 7,469
  • 4
  • 44
  • 48
0

This may or may not fit your needs, but a simple common interface sounds like what you want:

class Z_interface{ //abstract interface
public:
    virtual ~Z_interface() {} //virtual destructor
    virtual void func()=0; //virtual member
};

template <class T,class A>
class Z : public Z_interface { //implimentation
public:
    virtual ~Z_interface() {}
    virtual void func() {}
};

int main() {
    std::unique_ptr<Z_interface> ptr;
    switch(stuff) { //make the correct type
    case 0: ptr = std::unique_ptr<Z_interface>(new Z<int, char>()); break;
    case 1: ptr = std::unique_ptr<Z_interface>(new Z<int, short>()); break;
    case 2: ptr = std::unique_ptr<Z_interface>(new Z<long, char>()); break;
    case 3: ptr = std::unique_ptr<Z_interface>(new Z<long, short>()); break;
    };
    ptr->func(); //don't care about the type anymore, just the algorithms
}
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • I don't understand two things: a. Why after your solution I don't need 16 cases(with 4 types of T, and same for A)? b. What is the relations between class z and class z_interface? – yoni Dec 20 '11 at 19:40
  • @yoni: I forgot to make `Z` inherit from `Z_interface`. The switch needs 16 cases to _create_ the `Z` object, but everything after that can be the same code. `func` in my sample. – Mooing Duck Dec 20 '11 at 20:25