metaprogramming with variadic templates in C++ - c++

I am working on a simple game engine that provides a base class for game objects that can be extended with subclasses for the specific game. I need to write a function that can take a file, parse object names from it, and instantiate the corresponding objects in the game; providing a mechanism for storing level data in files. I had hoped to use metaprogramming to create a function that allows the caller to pass in a variable number of data types and generates a function that searches for names corresponding to those types in a file. Its use would look something along the lines of this (using templates):
fileParseFunction<type1, type2 type3>("filename");
would generate a function equivalent to:
fileParseFunction(string filename)
{
//code that opens file called "filename" and handles tokenizing/parsing
if(token == "type1")
{
gameWorld.add(new type1());
}
elseif(token == "type2")
{
gameWorld.add(new type2());
}
elseif(token == "type3")
{
gameWorld.add(new type3());
}
//other code to finish loading the level
}
Called with the parameter "filename". This should work for a variable number of types (3 in the example). I wrote some code to test the concept which involves generating a similar function. It uses templates to convert typename symbols to strings (this is needed for use in the comparisons in the function I eventually hope to write) and also variadic templates to generate a function that prints the names of all the types passed in as template parameters. Here it is:
#define TypeNameTemplate(a) template<> inline const char* typeName<a>(void) { return #a; }
template <typename T>
inline const char* typeName(void) { return "unknown"; }
TypeNameTemplate(int);
TypeNameTemplate(std::string);
TypeNameTemplate(double);
TypeNameTemplate(bool);
TypeNameTemplate(float);
/*template <>
inline const char* typeName<int>(void) { return "int"; }*/
template <typename T> inline void printtypes()
{
std::cout << typeName<T>();
}
template <typename T, typename... Args> void printtypes()
{
std::cout << typeName<T>() << std::endl;
printtypes<Args...>();
}
using namespace std;
int main()
{
//string a = typeName<int>();
//print();
printtypes<int, double, string, bool, float>();
return 0;
}
printtypes() should generate a function equivalent to:
void printtypes()
{
std::cout << typeName<int>();
std::cout << typeName<std:string>();
std::cout << typeName<double>();
std::cout << typeName<bool>();
std::cout << typeName<float>();
}
However, during compilation i get this error:
E:\C++ projects\templateTest\main.cpp:26:5: note: candidates are:
E:\C++ projects\templateTest\main.cpp:18:35: note: void printtypes() [with T = float]
E:\C++ projects\templateTest\main.cpp:23:46: note: void printtypes() [with T = float; Args = {}]
It appears that upon reaching the end up the variadic parameter pack recursively, the compiler does not know whether to call the template specialized on only one type with the last type in the pack, or the variadic template with the last type in the pack plus an empty parameter pack. Is what I'm attempting to do possible/practical in C++, and is there a way to let the compiler know that it should use the singe parameter template for the base/final case of the recursive call?

A simple solution is to add another explicit parameter to the second overload:
template <typename T, typename T2, typename... Args> void printtypes()
{
std::cout << typeName<T>() << std::endl;
printtypes<T2,Args...>();
}

While this answer does not answer your specific question about variadic templates, I hope it does answer your underlying question about how to make your game engine extensible.
What you came up with by creating your fileParseFunction() is an implementation of the Factory Method pattern. This is the main part that makes it easy to turn stored data into real objects. Unfortunately, it violates the Open-Close Principle making it difficult to reach your end goal, extendability.
For example, in your code above, your factory function can parse "type1", "type2" and "type3" from your data file and generate objects of type1, type2 and type3 but adding more types would mean editing this function and adding a new else if for every new type you wish to add
You've already identified this as a problem and are trying to solve it using variadic templates. Unfortunately, if you extend the number of game objects into the twenties, thirties, or even hundreds of types, variadic templates will become cumbersome to use, if at all they are able to go that far.
A much simpler solution is to use the Abstract Factory pattern. This essentially shifts responsibility for creating game objects from your file parser's Factory Function, to a factory object. Whether this transfer of power goes to a single function, or a fully-fledged class is up to you. You could also templatise this factory to save on coding.
Each of your factories will have to register their existence with the file parser before the parser is called and extending the parser's capabilities will be as simple as creating a new factory and registering it with the parser.
A simple example would be:
class GameObjectAbstractFactory {
public:
string registeredTypes() const{
// cycle through hash table to return the names of registered factories
}
GameObjectFactory* getFactory(string factoryName){
// return the registered factory, or nullptr if not registered
}
void registerFactory(string factoryName, GameObjectFactory*){
// add the factory if it doesn't exist
}
static GameObjectAbstractFactory* instance(){
// access to Singleton instance
}
private:
GameObjectAbstractFactory(); // enforces Singleton pattern
Hash<string, GameObjectFactory*> registeredFactories;
};
// Interface class for generating concrete types, can be templatised, depending on implementation
class GameObjectFactory{
public:
string name() = 0;
GameObject *createObject() = 0;
};
This would alter your parsing function so that it becomes:
fileParseFunction(string filename)
{
//code that opens file called "filename" and handles tokenizing/parsing
GameObjectAbstractFactory *abstractFactory = GameObjectAbstractFactory::instance();
GameObjectFactory *factory = abstractFactory.getFactory(token);
if(factory != nullptr)
{
gameWorld.add(factory.createObject());
}
//other code to finish loading the level
}
This would then make your fileParseFunction() compliant with the Open-Close Principle in that it could still generate new game objects as your engine is extended but the function itself will not have to be modified in order to do so.
There is a caveat with this pattern though: all the factories need to be registered with the abstract factory before they are needed, otherwise the required game object will not be able to be created.
As I mentioned in the beginning, this answer does not address your direct question about variadic templates but I hope this helps with the extendability of your game engine.

Related

Correct usage of ellipsis and template parameters

Turns out I need to build a function that takes a variable number of arguments of no predetermined types,something like:
myFun(int param1, char param2, short param3....);
And I thought about using variadic template functions.
This is actually a member function of a class which is inside a namespace, this is my header file:
//USART.hh file
namespace usartNameSpace
{
class USART
{
public:
USART();
~USART();
template <typename firstArgument, typename ...Arguments> bool parseUserCommands(firstArgument &argument, Arguments &... args);
};
}
This is the implementation(I have omitted both the constructor and destructor)
//USART.cpp file
using namespace usartNameSpace;
template <typename firstArgument, typename ...Arguments> bool USART::parseUsercommands(firstArgument &argument, Arguments&... args)
{
//stuff the function does
}
I will say it again, my goal is to be able to create a method that takes a variable number of parameters of no particular type, with this conception I think I'm able to reach that, however, when calling the method from the main.cpp file, I get the following error at compile time:
undefined reference to `bool usartNameSpace::USART::parseUserCommands<int, char>(int&, char&)'
collect2: error: ld returned 1 exit status
make: *** [makefile:68: mainProject.elf] Error 1
I do not really know what is wrong with my conception of things here, someone told me to try to put the implementation in the same header where the definition lies but that did not work neither(If someone could explain this one also, it would be very nice).
Lastly, here is my main file:
#include "USART.hh"
usartNameSpace::USART coms(USART2);
int n = 8;
char m = 'a';
int main(void)
{
coms.parseUserCommands<int, char>(n, m);
return 0;
}
Template Definition vs Declaration TL;DR
Put the definition of template functions, classes and methods (if isolated to a single class method) in the header file. Anything else can be defined in a source file.
Longer
The problem is that is not possible to have templates definitions (classes, functions and methods) in source files as the compiler need to know the instantiated type when it compiles the file, it can't leave it as a template parameter. In this case you have to put the definition of the template method with its declaration in the header. However, this doesn't mean you have to put non-template method's definitions in the same header, you can even create methods with the same name but aren't templated and split the declaration and definition (as far as my brief testing went).
Variadic Template Use
The pattern you appear to be using is a recursive template parameter function (method in this case but works for both). The key is that this is a recursive pattern thus you need a base method that just takes one (in this case template) argument. The recursive function takes a template initial argument and a second variadic parameter pack. You do what you want with the first argument, then call the method again parsing the variadic arguments (args... with the ellipsis). This will unfold the pack until you it the base class.
Another method would be to take a tuple of variadic arguments and manipulate the tuple so you can access all of the elements in a single function call, removing the need for a recursive variadic call pattern.
You could also (I believe) use std::make_tuple on the variadic pack to make it into a std::tuple and in that case you wouldn't need recursive pattern or the firstArgument parameter, just a function that take Args... args but I didn't explore that in testing. Some homework for you.
Code
Note: This is the code that was tested (briefly). I didn't explore in depth the solution with tuples but provided resources below that will hopefully guide you.
/// USART.hh
/// \note added header guards for completeness
#ifndef USART_H ///< header guard
#define USART_H
#include <iostream>
#include <string>
namespace usartNameSpace
{
class USART
{
public:
USART();
~USART();
/// Base case for recursive call
template<typename FirstA>
bool parseUserCommands(FirstA first)
{
std::cout << first << std::endl;
return true;
}
/// Variadic Resursive call
template<typename FirstA, typename... Args>
bool parseUserCommands(FirstA first, Args... args)
{
std::cout << first << std::endl;
return parseUserCommands(args...);
}
/// Non-template method with the same name as a templated method
bool parseUserCommands();
/// Non template method
void printer(std::string str);
};
}
#endif // USART_H
/// USART.cpp
#include <USART.hh>
namespace usartNameSpace
{
/// Implement all non-template methods in source file (*.cpp)
USART::USART()
{ std::cout << "USART constructor" << std::endl; }
USART::~USART()
{ std::cout << "USART destructor" << std::endl; }
bool USART::parseUserCommands()
{
std::cout << "No arguments" << std::endl;
return true;
}
void USART::printer(std::string str)
{ std::cout << str << std::endl; }
}
/// main.main.cpp
#include <USART.hh>
#include <iostream>
auto main() -> int
{
auto n = 8;
auto c = 'a';
auto s = "Hello";
auto b = true;
usartNameSpace::USART usart;
usart.parseUserCommands(n, c); ///< Two arguments
usart.parseUserCommands(s); ///< One argument
usart.parseUserCommands(n, c, s, b); ///< Four arguments
usart.printer("Bye!"); ///< Non-template method
usart.parseUserCommands(); ///< Non-template method of same name as templated one
return 0;
}
# Output
# Build and run instructions included for completeness
# I can provide a manual build command if requested.
$ bpt build -t :c++20:gcc-11 -o build
$ ./build/main
USART constructor
8
a
Hello
8
a
Hello
1
Bye!
No arguments
USART destructor
Compilers and Tools
GCC-11.3.0
bpt build system
Links and Resources Used
Variadic member function of template class : SO
Why can templates only be implemented in the header file? : SO
Pretty-print std::tuple : SO
For exploring manipulation parameter packs , tuples and variadic fold expressions
Parameter pack : cppreference
std::tuple : cppreference
std::make_tuple : cppreference

Generic Messaging when concrete Messages are autogenerated C++ classes from XML

Background
I have auto generated concrete message types from a XML -> C++ generator.
GenMsg1, GenMsg2, ... , GenMsgN
All of these generated classes are from an XML schema. Technically I can edit their cpp and hpp files but I would prefer to not touch these as much as possible. They all have guaranteed functions that I would like to be able to call generically.
NOTE: I cannot get away from the above situation as this is a design limitation from another project. Also, I just used raw pointers in this simple example. I understand this is not best practice, its just for showing a general idea.
Goal
I am looking to process the above generated messages generically on my side.
Idea 1 and 2
My first idea was to just create and general "Message" class that was templated to hold one of the above types with a simple enum for identifying what type of message it is. The problem with this is I cannot just pass around a pointer to Message because it needs the template type parameter so this is obviously a no-go.
My next thought was to use the Curiously Recurring Template Pattern but that has the same issues as above.
Idea 3
After a lot of reading on messaging frameworks my next thought was that std::variant might be an option.
I have the following example which works but it uses double pointers and templated functions to access. If the wrong datatype is used this will throw an exception at runtime (which makes it quite clear this is the issue) but I could see this being annoying down the line as far as tracking the source of the throw.
I keep trying to read up on the std::visit but it does not make a whole lot of sense to me. I do not really want to implement a separate visitor class with a bunch of functions by hand when all of the functions in the generated classes are autogenerated already(like foo in the example below) and are ready to be called when the type is known. Additionally, they are guaranteed to exist. So it would be kind of nice to be able to call a foo() in Message and have it dive into the internal Representation and call its foo.
I have a MsgType enum in there that I could use as well. When the internal representation is set, I could set that and use it for deducing type... But this seems like its just duplicating effort already done by the std::variant so I scrapped its use but kept it in the code blow in case someone here had a new idea where something like that could be useful.
Any ideas on design moving forward? This seems like the most promising route, but I am open to ideas. Also, with my reality of having to conform to other peoples design decisions I realize that this code will "smell" a bit no matter what. I am just trying to make it as clean as possible on my end.
Idea 3 Code
#include <iostream>
#include <variant>
enum class MsgType { NOTYPE = 0, GenMessage1 = 1, GenMessage2 = 2, GenMessage3 = 3 };
class GenMessage1
{
public:
void foo() {std::cout << "Msg 1" << std::endl;}
};
class GenMessage2
{
public:
void foo() { std::cout << "Msg 2" << std::endl; }
};
class GenMessage3
{
public:
void foo() { std::cout << "Msg 3" << std::endl; }
};
class Message
{
private:
MsgType msgType;
std::string xmlStrRep;
std::variant<GenMessage1*, GenMessage2*, GenMessage3*> internalRep;
public:
Message()
{
this->msgType = MsgType::NOTYPE;
this->xmlStrRep = "";
}
template <typename T>
void setInternalRep(T* internalRep)
{
this->internalRep = internalRep;
}
template <typename T>
void getInternalRep(T retrieved)
{
*retrieved = getInternalRepHelper(*retrieved);
}
template <typename T>
T getInternalRepHelper(T retrieved)
{
return std::get<T>(this->internalRep);
}
void foo()
{
//call into interal representation and call its foo
}
};
int main()
{
Message* msg = new Message();
GenMessage3* incomingMsg = new GenMessage3();
GenMessage3* retrievedMsg;
msg->setInternalRep(incomingMsg);
msg->getInternalRep(&retrievedMsg);
retrievedMsg->foo();
return 0;
}
Outputs:
Msg 3
I think std::visit is, as you suspected, what you need. You can implement your foo() function like this:
void foo()
{
std::visit([](auto* message) {message->foo();}, this->internalRep);
}
Using a generic lambda (taking auto), it can be thought of as a template function, where the lambda's argument message is the actual type of the message in the variant, and you can use it directly. Provided all the messages have the same interface that you want to use, then you can do this with all the interface functions.

map of pointers to functions of different return types and signatures

I am looking for a way to call different functions by a string input.
I have a map that ties each unique string to a function pointer and a lookup function to search the map and return a pointer if found.
Now the trick is, I need a way to store and return pointers to functions with at least different return types, if possible, also with different signatures.
The usage would be:
Get a string input from a network socket ->
find and execute the found function -> shove the result straight back into the socket to be serialized and sent, not caring what actually happened.
Is this doable? If not, how would one approach this task?
That can be done with a bit of boilerplate code in different ways. If the number of signatures is small enough you can hold multiple vectors of function pointers (one per function type) and then a map that maps the function name with a type identifier (used to select the vector) and the position within the vector.
The second option would be to store a boost::variant (again, if the set of signatures is small). You would need to provide a visitor object that evaluates the function (for each function type stored) and yields the result. The type is managed by the boost::variant type so there would be no need for the type tag to be stored in the map.
You can also use full type erasure and store in the map a tag determining the type of function to be called and a boost::any object storing the function pointer. You can use the type information to retrieve the pointer and execute the function, but you will have to manually handle the switch based on function type.
The simplest approach, on the other hand, is to write adapters that have a fixed interface. Then just store the pointers to the adapters in the map.
While you can't store different function pointers, you can store objects which contain those functions.
#include <iostream>
#include <cmath>
#include <map>
#include <string>
using namespace std;
class Functor{
public:
template<class T>
void operator()(T data){}
};
template<class T>
class BaseFunctor : public Functor{
public:
virtual void CallFunction(T data){ }
};
class FunctionPointer1 : public BaseFunctor<void *>{
public:
void doFunction1(){
cout << "Do Function 1"<<endl;
}
template<class T>
void CallFunction(T data){ doFunction1(); }
template<class T>
void operator()(T data){ this->CallFunction(data); }
};
class FunctionPointer2 : public BaseFunctor<int>{
public:
void doFunction2(int variable){ cout << "Do function 2 with integer variable" << variable <<endl; }
template<class T>
void CallFunction(T data) { doFunction2(data);}
template<class T>
void operator()(T data){ this->CallFunction(data); }
};
class FunctionPerformer{
private:
map<string,Functor> functions;
public:
FunctionPerformer(){
//init your map.
FunctionPointer1 function1;
FunctionPointer2 function2;
//-- follows
functions["Function1"] = function1;
functions["Functions2"] = function2;
//-- follows
}
Functor getFunctionFromString(string str){
return functions[str]
}
};
int main(int argc, char *argv[])
{
map<string,Functor> functions;
FunctionPerformer performer;
Functor func1, func2; // to hold return values from perfomer()
FunctionPointer1 *fn1; // to casting and execute the functions
FunctionPointer2 *fn2; // to casting and execute the functions
func1 = performer.getFunctionFromString("Function1");//get data
func2 = performer.getFunctionFromString("Function2");
//following two lines to cast the object and run the methods
fn1 = reinterpret_cast<FunctionPointer1 *>(&func1);
(*fn1)(NULL);
//following two lines to cast the object and run the methods
fn2 = reinterpret_cast<FunctionPointer2 *>(&func2);
(*fn2)(10);
system("Pause");
return 0;
}
I think the edited part makes it clearer?
This code can be optimized a little. Play around with it.
This is doable in C++11 with Variadic Templates. Check my answer at https://stackoverflow.com/a/33837343/1496826
No, it's really not doable, you need a real interpreted language if you want to do something like this. As soon as the signature is not constant then you need something a lot more involved.
How about making all those functions have the same signature? You could make all return types implement an interface, or use a collection, class, union or struct. Same for the arguments.
Can't you use specialization and templates to work around the issue?
template <class T>
T FooBar(void * params);
template<> int FooBar<int>( void * params );
template<> char FooBar<char>( void * params );
Instead of storing the function pointers themselves, which are too different from one another to be accommodated into the same data structure, you can store adaptors that take care of bridging the mismatch. This is a form of type-erasure. An example:
// Imaginary important resources
blaz_type get_blaz();
qux_type get_qux();
// The functions we'd like to put in our map
int foo(blaz_type);
std::string bar(qux_type);
using context_type = std::tuple<blaz_type, qux_type>;
using callback_type = std::function<void(context_type, socket_type&)>;
using std::get;
std::map<std::string, callback_type> callbacks = {
{
"foo"
, [](context_type context, socket_type& out)
{ marshall(out, foo(get<0>(std::move(context)))); }
}
, {
"bar"
, [](context_type context, socket_type& out)
{ marshall(out, bar(get<1>(std::move(context)))); }
}
};
In this example the adaptors are not stateful so you can actually use void (*)(context_type, socket_type&) as the callback_type.
Do note that this kind of design is a bit brittle in that the context_type needs to know about every kind of parameter a stored callback might ever need. If at some later point you need to store a callback which needs a new kind of parameter, you need to modify context_type -- if you improve the above design not to use magic numbers like 0 and 1 as parameters to std::get you could save yourself some pains (especially in the reverse situation of removing types from context_type). This is not an issue if all callbacks take the same parameters, in which case you can dispense yourself with the context_type altogether and pass those parameters to the callbacks directly.
Demonstration on LWS.

Automatically Instantiating over a bunch of types in C++

In our library we have a number of "plugins", which are implemented in their own cpp files. Each plugin defines a template function, and should instantiate this function over a whole bunch of types. The number of types can be quite large, 30-100 of them, and can change depending on some compile time options. Each instance really have to be compiled and optimized individually, the performance improves by 10-100 times. The question is what is the best way to instantiate all of these functions.
Each plugin is written by a scientist who does not really know C++, so the code inside each plugin must be hidden inside macros or some simple construct. I have a half-baked solution based on a "database" of instances:
template<int plugin_id, class T>
struct S
{
typedef T (*ftype)(T);
ftype fp;
};
// By default we don't have any instances
template<int plugin_id, class T> S::ftype S::fp = 0;
Now a user that wants to use a plugin can check the value of
S<SOME_PLUGIN,double>::fp
to see if there is a version of this plugin for the double type. The template instantiation of fp will generate a weak reference, so the linker will use the "real" instance if we define it in a plugin implementation file. Inside the implementation of SOME_PLUGIN we will have an instantiation
template<> S<SOME_PLUGIN,double>::ftype S<SOME_PLUGIN,double>::fp =
some_plugin_implementation;
This seems to work. The question is if there is some way to automatically repeat this last statement for all types of interest. The types can be stored in a template class or generated by a template loop. I would prefer something that can be hidden by a macro. Of course this can be solved by an external code generator, but it's hard to do this portably and it interfers with the build systems of the people that use the library. Putting all the plugins in header files solves the problem, but makes the compiler explode (needing many gigabytes of memory and a very long compilation time).
I've used http://www.boost.org/doc/libs/1_44_0/libs/preprocessor/doc/index.html for such magic, in particular SEQ_FOR_EACH.
You could use a type list from Boost.MPL and then create a class template that recursively eats that list and instantiates every type. This would however make them all nested structs of that class template.
Hmm, I don't think I understand your problem correctly, so apologies if this answer is way off the mark, but could you not have a static member of S, which has a static instance of ftype, and return a reference to that, this way, you don't need to explicitly have an instance defined in your implementation files... i.e.
template<int plugin_id, class T>
struct S
{
typedef T (*ftype)(T);
static ftype& instance()
{
static ftype _fp = T::create();
return _fp;
}
};
and instead of accessing S<SOME_PLUGIN,double>::fp, you'd do S<SOME_PLUGIN,double>::instance(). To instantiate, at some point you have to call S<>::instance(). Do you need this to happen automagically as well?
EDIT: just noticed that you have a copy constructor, for ftype, changed the above code.. now you have to define a factory method in T called create() to really create the instance.
EDIT: Okay, I can't think of a clean way of doing this automatically, i.e. I don't believe there is a way to (at compile time) build a list of types, and then instantiate. However you could do it using a mix... Hopefully the example below will give you some ideas...
#include <iostream>
#include <typeinfo>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/algorithm.hpp>
using namespace std;
// This simply calls the static instantiate function
struct instantiate
{
template <typename T>
void operator()(T const& x) const
{
T::instance();
}
};
// Shared header, presumably all plugin developers will use this header?
template<int plugin_id, class T>
struct S
{
typedef T (*ftype)(T);
static ftype& instance()
{
cout << "S: " << typeid(S<plugin_id, T>).name() << endl;
static ftype _fp; // = T::create();
return _fp;
}
};
// This is an additional struct, each plugin developer will have to implement
// one of these...
template <int plugin_id>
struct S_Types
{
// All they have to do is add the types that they will support to this vector
static void instance()
{
boost::fusion::vector<
S<plugin_id, double>,
S<plugin_id, int>,
S<plugin_id, char>
> supported_types;
boost::fusion::for_each(supported_types, instantiate());
}
};
// This is a global register, so once a plugin has been developed,
// add it to this list.
struct S_Register
{
S_Register()
{
// Add each plugin here, you'll only have to do this when a new plugin
// is created, unfortunately you have to do it manually, can't
// think of a way of adding a type at compile time...
boost::fusion::vector<
S_Types<0>,
S_Types<1>,
S_Types<2>
> plugins;
boost::fusion::for_each(plugins, instantiate());
}
};
int main(void)
{
// single instance of the register, defining this here, effectively
// triggers calls to instanc() of all the plugins and supported types...
S_Register reg;
return 0;
}
Basically uses a fusion vector to define all the possible instances that could exist. It will take a little bit of work from you and the developers, as I've outlined in the code... hopefully it'll give you an idea...

Where do you find templates useful?

At my workplace, we tend to use iostream, string, vector, map, and the odd algorithm or two. We haven't actually found many situations where template techniques were a best solution to a problem.
What I am looking for here are ideas, and optionally sample code that shows how you used a template technique to create a new solution to a problem that you encountered in real life.
As a bribe, expect an up vote for your answer.
General info on templates:
Templates are useful anytime you need to use the same code but operating on different data types, where the types are known at compile time. And also when you have any kind of container object.
A very common usage is for just about every type of data structure. For example: Singly linked lists, doubly linked lists, trees, tries, hashtables, ...
Another very common usage is for sorting algorithms.
One of the main advantages of using templates is that you can remove code duplication. Code duplication is one of the biggest things you should avoid when programming.
You could implement a function Max as both a macro or a template, but the template implementation would be type safe and therefore better.
And now onto the cool stuff:
Also see template metaprogramming, which is a way of pre-evaluating code at compile-time rather than at run-time. Template metaprogramming has only immutable variables, and therefore its variables cannot change. Because of this template metaprogramming can be seen as a type of functional programming.
Check out this example of template metaprogramming from Wikipedia. It shows how templates can be used to execute code at compile time. Therefore at runtime you have a pre-calculated constant.
template <int N>
struct Factorial
{
enum { value = N * Factorial<N - 1>::value };
};
template <>
struct Factorial<0>
{
enum { value = 1 };
};
// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
int x = Factorial<4>::value; // == 24
int y = Factorial<0>::value; // == 1
}
I've used a lot of template code, mostly in Boost and the STL, but I've seldom had a need to write any.
One of the exceptions, a few years ago, was in a program that manipulated Windows PE-format EXE files. The company wanted to add 64-bit support, but the ExeFile class that I'd written to handle the files only worked with 32-bit ones. The code required to manipulate the 64-bit version was essentially identical, but it needed to use a different address type (64-bit instead of 32-bit), which caused two other data structures to be different as well.
Based on the STL's use of a single template to support both std::string and std::wstring, I decided to try making ExeFile a template, with the differing data structures and the address type as parameters. There were two places where I still had to use #ifdef WIN64 lines (slightly different processing requirements), but it wasn't really difficult to do. We've got full 32- and 64-bit support in that program now, and using the template means that every modification we've done since automatically applies to both versions.
One place that I do use templates to create my own code is to implement policy classes as described by Andrei Alexandrescu in Modern C++ Design. At present I'm working on a project that includes a set of classes that interact with BEA\h\h\h Oracle's Tuxedo TP monitor.
One facility that Tuxedo provides is transactional persistant queues, so I have a class TpQueue that interacts with the queue:
class TpQueue {
public:
void enqueue(...)
void dequeue(...)
...
}
However as the queue is transactional I need to decide what transaction behaviour I want; this could be done seperately outside of the TpQueue class but I think it's more explicit and less error prone if each TpQueue instance has its own policy on transactions. So I have a set of TransactionPolicy classes such as:
class OwnTransaction {
public:
begin(...) // Suspend any open transaction and start a new one
commit(..) // Commit my transaction and resume any suspended one
abort(...)
}
class SharedTransaction {
public:
begin(...) // Join the currently active transaction or start a new one if there isn't one
...
}
And the TpQueue class gets re-written as
template <typename TXNPOLICY = SharedTransaction>
class TpQueue : public TXNPOLICY {
...
}
So inside TpQueue I can call begin(), abort(), commit() as needed but can change the behaviour based on the way I declare the instance:
TpQueue<SharedTransaction> queue1 ;
TpQueue<OwnTransaction> queue2 ;
I used templates (with the help of Boost.Fusion) to achieve type-safe integers for a hypergraph library that I was developing. I have a (hyper)edge ID and a vertex ID both of which are integers. With templates, vertex and hyperedge IDs became different types and using one when the other was expected generated a compile-time error. Saved me a lot of headache that I'd otherwise have with run-time debugging.
Here's one example from a real project. I have getter functions like this:
bool getValue(wxString key, wxString& value);
bool getValue(wxString key, int& value);
bool getValue(wxString key, double& value);
bool getValue(wxString key, bool& value);
bool getValue(wxString key, StorageGranularity& value);
bool getValue(wxString key, std::vector<wxString>& value);
And then a variant with the 'default' value. It returns the value for key if it exists, or default value if it doesn't. Template saved me from having to create 6 new functions myself.
template <typename T>
T get(wxString key, const T& defaultValue)
{
T temp;
if (getValue(key, temp))
return temp;
else
return defaultValue;
}
Templates I regulary consume are a multitude of container classes, boost smart pointers, scopeguards, a few STL algorithms.
Scenarios in which I have written templates:
custom containers
memory management, implementing type safety and CTor/DTor invocation on top of void * allocators
common implementation for overloads wiht different types, e.g.
bool ContainsNan(float * , int)
bool ContainsNan(double *, int)
which both just call a (local, hidden) helper function
template <typename T>
bool ContainsNanT<T>(T * values, int len) { ... actual code goes here } ;
Specific algorithms that are independent of the type, as long as the type has certain properties, e.g. binary serialization.
template <typename T>
void BinStream::Serialize(T & value) { ... }
// to make a type serializable, you need to implement
void SerializeElement(BinStream & strean, Foo & element);
void DeserializeElement(BinStream & stream, Foo & element)
Unlike virtual functions, templates allow more optimizations to take place.
Generally, templates allow to implement one concept or algorithm for a multitude of types, and have the differences resolved already at compile time.
We use COM and accept a pointer to an object that can either implement another interface directly or via [IServiceProvider](http://msdn.microsoft.com/en-us/library/cc678965(VS.85).aspx) this prompted me to create this helper cast-like function.
// Get interface either via QueryInterface of via QueryService
template <class IFace>
CComPtr<IFace> GetIFace(IUnknown* unk)
{
CComQIPtr<IFace> ret = unk; // Try QueryInterface
if (ret == NULL) { // Fallback to QueryService
if(CComQIPtr<IServiceProvider> ser = unk)
ser->QueryService(__uuidof(IFace), __uuidof(IFace), (void**)&ret);
}
return ret;
}
I use templates to specify function object types. I often write code that takes a function object as an argument -- a function to integrate, a function to optimize, etc. -- and I find templates more convenient than inheritance. So my code receiving a function object -- such as an integrator or optimizer -- has a template parameter to specify the kind of function object it operates on.
The obvious reasons (like preventing code-duplication by operating on different data types) aside, there is this really cool pattern that's called policy based design. I have asked a question about policies vs strategies.
Now, what's so nifty about this feature. Consider you are writing an interface for others to use. You know that your interface will be used, because it is a module in its own domain. But you don't know yet how people are going to use it. Policy-based design strengthens your code for future reuse; it makes you independent of data types a particular implementation relies on. The code is just "slurped in". :-)
Traits are per se a wonderful idea. They can attach particular behaviour, data and typedata to a model. Traits allow complete parameterization of all of these three fields. And the best of it, it's a very good way to make code reusable.
I once saw the following code:
void doSomethingGeneric1(SomeClass * c, SomeClass & d)
{
// three lines of code
callFunctionGeneric1(c) ;
// three lines of code
}
repeated ten times:
void doSomethingGeneric2(SomeClass * c, SomeClass & d)
void doSomethingGeneric3(SomeClass * c, SomeClass & d)
void doSomethingGeneric4(SomeClass * c, SomeClass & d)
// Etc
Each function having the same 6 lines of code copy/pasted, and each time calling another function callFunctionGenericX with the same number suffix.
There were no way to refactor the whole thing altogether. So I kept the refactoring local.
I changed the code this way (from memory):
template<typename T>
void doSomethingGenericAnything(SomeClass * c, SomeClass & d, T t)
{
// three lines of code
t(c) ;
// three lines of code
}
And modified the existing code with:
void doSomethingGeneric1(SomeClass * c, SomeClass & d)
{
doSomethingGenericAnything(c, d, callFunctionGeneric1) ;
}
void doSomethingGeneric2(SomeClass * c, SomeClass & d)
{
doSomethingGenericAnything(c, d, callFunctionGeneric2) ;
}
Etc.
This is somewhat highjacking the template thing, but in the end, I guess it's better than play with typedefed function pointers or using macros.
I personally have used the Curiously Recurring Template Pattern as a means of enforcing some form of top-down design and bottom-up implementation. An example would be a specification for a generic handler where certain requirements on both form and interface are enforced on derived types at compile time. It looks something like this:
template <class Derived>
struct handler_base : Derived {
void pre_call() {
// do any universal pre_call handling here
static_cast<Derived *>(this)->pre_call();
};
void post_call(typename Derived::result_type & result) {
static_cast<Derived *>(this)->post_call(result);
// do any universal post_call handling here
};
typename Derived::result_type
operator() (typename Derived::arg_pack const & args) {
pre_call();
typename Derived::result_type temp = static_cast<Derived *>(this)->eval(args);
post_call(temp);
return temp;
};
};
Something like this can be used then to make sure your handlers derive from this template and enforce top-down design and then allow for bottom-up customization:
struct my_handler : handler_base<my_handler> {
typedef int result_type; // required to compile
typedef tuple<int, int> arg_pack; // required to compile
void pre_call(); // required to compile
void post_call(int &); // required to compile
int eval(arg_pack const &); // required to compile
};
This then allows you to have generic polymorphic functions that deal with only handler_base<> derived types:
template <class T, class Arg0, class Arg1>
typename T::result_type
invoke(handler_base<T> & handler, Arg0 const & arg0, Arg1 const & arg1) {
return handler(make_tuple(arg0, arg1));
};
It's already been mentioned that you can use templates as policy classes to do something. I use this a lot.
I also use them, with the help of property maps (see boost site for more information on this), in order to access data in a generic way. This gives the opportunity to change the way you store data, without ever having to change the way you retrieve it.