Metaprogramming with Templates (question)

Started by
4 comments, last by Zahlman 14 years, 11 months ago
From explanations of metaprogramming with templates (in C++), there's still something that I wasn't sure about. Are templates limited to creating classes at compile-time, or any time (dynamically)? For example, what if I wanted my program to run for a while, and with changing conditions, create a new class from the template with a different type. A more concrete example: Let's say you have a template that contains a generic search algorithm somewhere in it and you don't know beforehand what type will be best suited for the future tasks. While running, you may want this template to generate a new class (not originally planned for) if a different search algorithm is preferable. Is this feasible, or must I recompile the project? Thank you.
Advertisement
Template or not, you can never create a new class in C++ at run time baring some special code that calls the compiler or some such. Also I don't really understand your example. It sounds more like something that is done with straight virtuals but I can't be sure. What exactly are you trying to do?
Most probably: To expand your C++ program in future, without the need to completely recompile and redistribute the program, which is related to what is called "plugins", your application needs to be able to bind to shared libraries (a.k.a. DLL's).

Templates are to be evaluated/substituted fully at compile-time (as compared to generics, e.g. in C#), which is a pro and a con of C++ templates. So if you want to use different parameters for your templates in the future, that must happen before compilation.

[Edited by - phresnel on April 29, 2009 4:06:05 AM]
Sounds like you are trying to do reflection, but afaik, c++ does not support it.

is this what you are trying to do?
http://en.wikipedia.org/wiki/Reflection_(computer_science)
www.ageofconan.com
Any programming involving templates is all sorted out at compile time. The main deal about template metaprogramming is you move work from run time to compile time, and thats it really.

Straight up C++ offers little for reflection, but a book on C++/CLI I have makes mention about this ability, though even then it was kinda vague about possible uses (mentions this is the kind of stuff a compiler does).
Templated classes give you a way of defining multiple types. This happens at compile time; you cannot invent a new kind of data in the middle of running the program.

If you have a template class Foo<T>, and there is a line of code in your program somewhere that instantiates a Foo<int>, then Foo<int> is a type. Foo&;lt;double>, however, is not, unless you instantiate the template (even though 'double' is a type).

However, it is possible to cause all the Foo<T>s that do exist to be related to each other by inheritance. Say for example that we define Foo<T> to derive from FooBase. This allows you to have a variable of type pointer-to-FooBase, and at runtime, decide exactly what kind of FooBase it points at - where the possibilities are any Foo<T> template instantiation (or the base FooBase itself). Totally useless example:

#include <iostream>#include <string>class Printable {  public:  virtual void print(std::ostream& os) const = 0;  ~Printable();};Printable::~Printable() {}std::ostream& operator<<(std::ostream& os, const Printable& p) {  p.print(os);  return os;}template <typename T>class PrintableValue : public Printable {  T value;  public:  PrintableValue(const T& value) : value(value) {}  void print(std::ostream& os) const;};template <typename T>void PrintableValue<T>::print(std::ostream& os) const {  os << value;}template <typename T>PrintableValue<T>* make_printable(const T& value) {  return new PrintableValue<T>(value);}int main(int argc, char** argv) {  Printable* p;  if (argc < 2) { p = make_printable(42); }  else { p = make_printable(std::string("hi mom")); }  std::cout << *p;  delete p;}


Here, the template types PrintableValue<int> and PrintableValue<std::string> are implicitly instantiated. The appropriate type is selected, dynamically instantiated, and pointed at by the base class pointer. The operator overload then makes a virtual call to print(), which is selected from the appropriate derived class.

(Note that the template will not work with a string literal, because the constructor would fail to compile: you can't initialize a member from an array. Since you can't assign from an array, either, you'd probably have to specialize the template for array types.)

This topic is closed to new replies.

Advertisement