Do templates support variable numbers of parameters - c++

I'm trying to determine if the following scenario is appropriate for a template, and if so how it would be done.
I have a base class, event_base. It is inherited by specific types of events.
class event_base_c {
//... members common to all events ...
// serialize the class for transmision
virtual std::string serialize(void);
};
class event_motion_c : public event_base_c {
//... members for a motion event ...
// serialize the class for transmission
virtual std::string serialize(void);
};
class event_alarm_c : public event_base_c {
//... members for a motion event ...
// serialize the class for transmission
virtual std::string serialize(void);
};
Events get serialized and sent from one various process to an event logger, which recreates the event object from the serialized data.
My question is with regards to the processes that are sending the events. We cannot include a 'send()' method in the event class. I have been told that I need to create an event_sender object that knows how to send the serialized event. So the code from one process might be:
if (motion_detected on sensor1) {
event_motion_c Event(sensor1, x, y, z);
event_sender EventSender;
EventSender.report(Event.serialize());
}
While some other process might report an alarm using similar code such as:
if (alarm) {
event_alarm_c Event(alarm_id, alarm_type);
event_sender EventSender;
EventSender.report(Event.serialize());
}
This feels like a template candidate to me, but what stops/confuses me is that the constructor for the different event classes have different number of parameters. I do not know if templates support something like that, and if they do, I don't know the syntax for doing so.
I could easily define this as a macro such as:
#define SEND_EVENT(evt_class, args...) \
{ \
evt_class Event(#args); \
event_sender EventSender; \
\
EventSender.report(Event.serialize()); \
}
Then the coder would simply use:
SEND_EVENT(event_motion_c, sensor1, x, y, z);
and
SEND_EVENT(event_alarm_c, alarm_type);
But I am hesitant to make a macro for this.
Do templates support variable numbers of parameters? And if so, how is that done?

C++ does not support variadic templates, but C++0x will, and some compilers already have support for this (including G++ with the --std=c++0x flag). Wikipedia has examples of how to use this feature.

no.
In C++ variadic templates are not supported.
But you can easily overcome that by giving template defaults:
template<class I, class J = void>
struct S;
template<class, class> struct S {}; // two parameter
template<class I> struct S<I> {}; // "single" parameter, second parameter is void
S<int, int>; // two parameter instance
S<int>; // "single" parameter instance
the default does not have to be void type, it can be anything.
sometimes the style may become too messy (if you have lots of defaults), then you can use boost preprocessor, namely:
http://www.boost.org/doc/libs/1_43_0/libs/preprocessor/doc/ref/enum_params_with_a_default.html
http://www.boost.org/doc/libs/1_43_0/libs/preprocessor/doc/ref/enum_params.html
http://www.boost.org/doc/libs/1_43_0/libs/preprocessor/doc/ref/enum_binary_params.html

Variadic templates are an in-progress C++0x feature. You've been able to at least start using them as of GCC 4.3. I don't pay much attention to Microsoft.

Related

Attempting to improve a C++ template API

I am doodling with a binary packet parser leveraging template in attempt to create a "brick-by-brick" workflow. It is more about prototyping than performance. The basic idea is to configure a PacketParser with a bunch a Fields so it can parse a binary payload directly to a struct.
It is currently a satisfying MVP but I don't like the API:
...
struct MyStruct {
int value;
void setValue(int v) { value = v;}
}
ValueField<int, decltype(&MyStruct::setValue)> myField(&MyStruct::setValue);
PacketParser<decltype(myField)> myParser(myField);
MyStruct out{0};
auto error = myParser.parse(data, len, out);
...
That might not look so bad, but it quickly gets worst when more fields are involved:
ValueField<int, decltype(&MyStruct::setValue1)> myField1(&MyStruct::setValue1);
ValueField<int, decltype(&MyStruct::setValue2)> myField2(&MyStruct::setValue2);
ValueField<int, decltype(&MyStruct::setValue3)> myField3(&MyStruct::setValue3);
PacketParser<decltype(myField1), decltype(myField2), decltype(myField3)> myParser(myField1, myField2, myField3);
Yep... decltype everywhere. The reason it is this way is that ValueField must hold an instance of the method pointer (provided in the constructor) but the templated struct still needs to know the type of the setter before the constructor is called, because it could not be deduced so late, in my understanding.
template <class T, class SetterType>
struct ValueField {
const SetterType setter;
ValueField(SetterType s) : setter(s){}
};
The macro workaround is an obvious solution to compress the API, but I would like to find a solution making it less verbose without that, either by using a different pattern, obscure syntax, pointer gymnastics, etc.
I wasn't able to come up with something less complicated than writing decltype everywhere so far.

macro that defines entire derived class from one function and certain type specifiers?

I have a class called system. A system takes some object managers and changes all objects in them in some way.
For example there might be a system that draws all images in a imageManager.
Every derived class works somewhat like this (pseudo code):
class someChildClass : public System{
private:
someObjectManager &mang1; //these are used by the update method.
someOtherObjectManager &mang2;//the update method changes these somehow
public:
someChildClass(someObjectManager &mang1, someObjectManager &mang2)
:mang1(mang1),mang2(mang2){
}
virtual void update(){
//this is pure virtual in the System base class.
//Do something with the managers here
}
}
I feel like writing everything but the update method is a waste of time and a source of errors. I wanted to write a macro that basically makes a class like this like so:
QUICKSYSTEM(thisIsTheSystemName, someObjectManager, mang1, someOtherObjectManager, mang2, ... (infinite possible Managers. So a variadic macro?)){
//this is the update function
}
}//this is the end braked for the class declaration. Its ugly but I dont know how I could do the function differently?
well I am having some problems making the macro. Everything works fine until I need to split the variadic arguments into the names and the types. I dont know if this is even possible now, since I cant go back and forth in the arguments easily or apply a easy step to them to make sure that every 2nd is the name of the variable. I would be ok with omitting the possibility for names and just had the types with some sort of automatic naming (manager1,manager2,manager3 or something like that).
If this isnt possible using a macro, what would be a better way to avoid mistakes and cut some time in the constructor and class declaration part?
Yeah, macros are really, really not the way to do this. C++ has templates, which follow C++ syntax and support C++ expressions. Macros instead use their own preprocessor language, which is almost entirely unaware of C++.
You'll want to read up a bit on std::tuple as well. It's going to be rather tricky to handle all those managers with those names. Tuples are the Standard solution for that. managers.get<0> and managers.get<someObjectManager> both work.
Variadic templates are the tool you need here:
#include <iostream>
#include <tuple>
#include <functional>
struct System { void virtual update() = 0; };
template<class... Managers>
struct ManagedSystem : System
{
std::function<void(Managers&...)> _update;
std::tuple<Managers&...> _managers;
template<class F>
ManagedSystem(F update, Managers&... managers) : _update(update), _managers(managers...) {}
void update() override { _update(std::get<Managers&>(_managers)...); }
};
int main()
{
int n = 0;
double d = 3.14;
auto reset = [](int& a, double& d) { a = 0; d = 0.0; };
ManagedSystem<int, double> ms{reset, n, d};
ms.update();
std::cout << "n = " << n << ", d = " << d << "\n";
// n = 0, d = 0
}
The idea is to define a templated-class (ManagedSystem) taking as template-parameters multiple manager types. This class inherits from Systemand provides a constructor taking:
an update functor,
and references to manager whose type is defined by the template parameters of the class.
The said managers are registered internally in an std::tuple and (with a bit of parameter pack magic fed to the update functor.
From there, you can define an inherited class from System by providing an update function and a type list. This avoids the use of ugly and type-unsafe macros in favor of the not-less ugly but type-string templates ;)

Calling different template function specialisations based on a run-time value

This is related to a previous question in that it's part of the same system, but it's a different problem.
I'm working on an in-house messaging system, which is designed to send messages (structs) to consumers.
When a project wants to use the messaging system, it will define a set of messages (enum class), the data types (struct), and the relationship between these entities:
template <MessageType E> struct expected_type;
template <> struct expected_type<MessageType::TypeA> { using type = Foo; };
template <> struct expected_type<MessageType::TypeB> { using type = Bar; };
template <> struct expected_type<MessageType::TypeM> { using type = Foo; };
Note that different types of message may use the same data type.
The code for sending these messages is discussed in my previous question. There's a single templated method that can send any message, and maintains type safety using the template definitions above. It works quite nicely.
My question regards the message receiver class. There is a base class, which implements methods like these:
ReceiveMessageTypeA(const Foo & data) { /* Some default action */ };
ReceiveMessageTypeB(const Bar & data) { /* Some default action */ };
ReceiveMessageTypeM(const Foo & data) { /* Some default action */ };
It then implements a single message processing function, like this:
bool ProcessMessage(MessageType msgType, void * data) {
switch (msgType) {
case TypeA:
ReceiveMessageTypeA(data);
break;
case TypeB:
ReceiveMessageTypeB(data);
break;
// Repeat for all supported message types
default:
// error handling
break;
}
}
When a message receiver is required, this base class is extended, and the desired ReceiveMessageTypeX methods are implemented. If that particular receiver doesn't care about a message type, the corresponding function is left unimplemented, and the default from the base class is used instead.
Side note: ignore the fact that I'm passing a void * rather than the specific type. There's some more code in between to handle all that, but it's not a relevant detail.
The problem with the approach is the addition of a new message type. As well as having to define the enum, struct, and expected_type<> specialisation, the base class has to be modified to add a new ReceiveMessageTypeX default method, and the switch statement in the ProcessMessage function must be updated.
I'd like to avoid manually modifying the base class. Specifically, I'd like to use the information stored in expected_type to do the heavy lifting, and to avoid repetition.
Here's my attempted solution:
In the base class, define a method:
template <MessageType msgType>
bool Receive(expected_type<msgType>::type data) {
// Default implementation. Print "Message not supported", or something
}
Then, the subclasses can just implement the specialisations they care about:
template<> Receive<MessageType::TypeA>(const Foo & data) { /* Some processing */ }
// Don't care about TypeB
template<> Receive<MessageType::TypeM>(const Foo & data) { /* Some processing */ }
I think that solves part of the problem; I don't need to define new methods in the base class.
But I can't figure out how to get rid of the switch statement. I'd like to be able to do this:
bool ProcessMessage(MessageType msgType, void * data) {
Receive<msgType>(data);
}
This won't do, of course, because templates don't work like that.
Things I've thought of:
Generating the switch statement from the expected_type structure. I have no idea how to do this.
Maintaining some sort of map of function pointers, and calling the desired one. The problem is that I don't know how to initialise the map without repeating the data from expected_type, which I don't want to do.
Defining expected_type using a macro, and then playing preprocessor games to massage that data into a switch statement as well. This may be viable, but I try to avoid macros if possible.
So, in summary, I'd like to be able to call a different template specialisation based on a run-time value. This seems like a contradiction to me, but I'm hoping someone can point me in a useful direction. Even if that is informing me that this is not a good idea.
I can change expected_type if needed, as long as it doesn't break my Send method (see my other question).
You had right idea with expected_type and Receive templates; there's just one step left to get it all working.
First, we need to give us some means to enumerate over MessageType:
enum class MessageType {
_FIRST = 0,
TypeA = _FIRST,
TypeB,
TypeM = 100,
_LAST
};
And then we can enumerate over MessageType at compile time and generate dispatch functions (using SFINAE to skip values not defined in expected_types):
// this overload works when expected_types has a specialization for this value of E
template<MessageType E> void processMessageHelper(MessageType msgType, void * data, typename expected_type<E>::type*) {
if (msgType == E) Receive<E>(*(expected_type<E>::type*)data);
else processMessageHelper<(MessageType)((int)E + 1)>(msgType, data, nullptr);
}
template<MessageType E> void processMessageHelper(MessageType msgType, void * data, bool) {
processMessageHelper<(MessageType)((int)E + 1)>(msgType, data, nullptr);
}
template<> void processMessageHelper<MessageType::_LAST>(MessageType msgType, void * data, bool) {
std::cout << "Unexpected message type\n";
}
void ProcessMessage(MessageType msgType, void * data) {
processMessageHelper<MessageType::_FIRST>(msgType, data, nullptr);
}
Your title says: "Calling different template function specialisations based on a run-time value"
That can only be done with some sort of manual switch statement, or with virtual functions.
On the one hand, it looks on the surface like you are doing object-oriented programming, but you don't yet have any virtual methods. If you find you are writing pseudo-objects everywhere, but you don't have any virtual functions, then it means you are not doing OOP. This is not a bad thing though. If you overuse OOP, then you might fail to appreciate the particular cases where it is useful and therefore it will just cause more confusion.
Simplify your code, and don't get distracted by OOP
You want the message type object to have some 'magic' associated with it, where it's MessageType controls how it is dispatched. This means you need a virtual function.
struct message {
virtual void Receive() = 0;
}
struct message_type_A : public message {
virtual void Receive() {
....
}
}
This allows you, where appropriate, to pass these objects as message&, and to call msg.process_me()

Multiple inheritance dilemma in C++

I'm facing problems with the design of a C++ library of mine. It is a library for reading streams that support a feature I haven't found on other "stream" implementations. It is not really important why I've decided to start writing it. The point is I have a stream class that provides two important behaviours through multiple inheritance: shareability and seekability.
Shareable streams are those that have a shareBlock(size_t length) method that returns a new stream that shares resources with its parent stream (e.g. using the same memory block used by parent stream). Seekable streams are those that are.. well, seekable. Through a method seek(), these classes can seek to a given point in the stream. Not all streams of the library are shareable and/or seekable.
A stream class that both provides implementation for seeking and sharing resources inherits interface classes called Seekable and Shareable. That's all good if I know the type of such a stream, but, sometimes, I might want a function to accept as argument a stream that simply fulfills the quality of being seekable and shareable at the same time, regardless of which stream class it actually is. I could do that creating yet another class that inherits both Seekable and Shareable and taking a reference to that type, but then I would have to make my classes that are both seekable and shareable inherit from that class. If more "behavioural classes" like those were to be added, I would need to make several modifications everywhere in the code, soon leading to unmaintainable code. Is there a way to solve this dilemma? If not, then I'm absolutely coming to understand why people are not satisfied by multiple inheritance. It almost does the job, but, just then, it doesn't :D
Any help is appreciated.
-- 2nd edit, preferred problem resolution --
At first I thought Managu's solution would be my preferred one. However, Matthieu M. came with another I preferred over Managu's: to use boost::enable_if<>. I would like to use Managu's solution if BOOST_MPL_ASSERT produced messages weren't so creepy. If there was any way to create instructive compile-time error messages, I would surely do that way. But, as I said, the methods available produce creepy messages. So I prefer the (much) lesser instructive, yet cleaner message produced when boost::enable_if<> conditions are not met.
I've created some macros to ease the task to write template functions that take arguments inheriting select class types, here they go:
// SonettoEnableIfDerivedMacros.h
#ifndef SONETTO_ENABLEIFDERIVEDMACROS_H
#define SONETTO_ENABLEIFDERIVEDMACROS_H
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/array/elem.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/utility/enable_if.hpp>
/*
For each (TemplateArgument,DerivedClassType) preprocessor tuple,
expand: `boost::is_base_and_derived<DerivedClassType,TemplateArgument>,'
*/
#define SONETTO_ENABLE_IF_DERIVED_EXPAND_CONDITION(z,n,data) \
boost::is_base_and_derived<BOOST_PP_TUPLE_ELEM(2,1,BOOST_PP_ARRAY_ELEM(n,data)), \
BOOST_PP_TUPLE_ELEM(2,0,BOOST_PP_ARRAY_ELEM(n,data))>,
/*
ReturnType: Return type of the function
DerivationsArray: Boost.Preprocessor array containing tuples in the form
(TemplateArgument,DerivedClassType) (see
SONETTO_ENABLE_IF_DERIVED_EXPAND_CONDITION)
Expands:
typename boost::enable_if<
boost::mpl::and_<
boost::is_base_and_derived<DerivedClassType,TemplateArgument>,
...
boost::mpl::bool_<true> // Used to nullify trailing comma
>, ReturnType>::type
*/
#define SONETTO_ENABLE_IF_DERIVED(ReturnType,DerivationsArray) \
typename boost::enable_if< \
boost::mpl::and_< \
BOOST_PP_REPEAT(BOOST_PP_ARRAY_SIZE(DerivationsArray), \
SONETTO_ENABLE_IF_DERIVED_EXPAND_CONDITION,DerivationsArray) \
boost::mpl::bool_<true> \
>, ReturnType>::type
#endif
// main.cpp: Usage example
#include <iostream>
#include "SonettoEnableIfDerivedMacros.h"
class BehaviourA
{
public:
void behaveLikeA() const { std::cout << "behaveLikeA()\n"; }
};
class BehaviourB
{
public:
void behaveLikeB() const { std::cout << "behaveLikeB()\n"; }
};
class BehaviourC
{
public:
void behaveLikeC() const { std::cout << "behaveLikeC()\n"; }
};
class CompoundBehaviourAB : public BehaviourA, public BehaviourB {};
class CompoundBehaviourAC : public BehaviourA, public BehaviourC {};
class SingleBehaviourA : public BehaviourA {};
template <class MustBeAB>
SONETTO_ENABLE_IF_DERIVED(void,(2,((MustBeAB,BehaviourA),(MustBeAB,BehaviourB))))
myFunction(MustBeAB &ab)
{
ab.behaveLikeA();
ab.behaveLikeB();
}
int main()
{
CompoundBehaviourAB ab;
CompoundBehaviourAC ac;
SingleBehaviourA a;
myFunction(ab); // Ok, prints `behaveLikeA()' and `behaveLikeB()'
myFunction(ac); // Fails with `error: no matching function for
// call to `myFunction(CompoundBehaviourAC&)''
myFunction(a); // Fails with `error: no matching function for
// call to `myFunction(SingleBehaviourA&)''
}
As you can see, the error messages are exceptionally clean (at least in GCC 3.4.5). But they can be misleading. It doesn't inform you that you've passed the wrong argument type. It informs you that the function doesn't exist (and, in fact, it doesn't due to SFINAE; but that may not be exactly clear to the user). Still, I prefer those clean messages over those randomStuff ... ************** garbage ************** BOOST_MPL_ASSERT produces.
If you find any bugs in this code, please edit and correct them, or post a comment in that regard. The one major issue I find in those macros is that they're limited to some Boost.Preprocessor limits. Here, for example, I can only pass a DerivationsArray of up to 4 items to SONETTO_ENABLE_IF_DERIVED(). I think those limits are configurable though, and maybe they will even be lifted in upcoming C++1x standard, won't they? Please, correct me if I'm wrong. I don't remember if they have suggested changes to the preprocessor.
Thank you.
Just a few thoughts:
STL has this same sort of problem with iterators and functors. The solution there was basically to remove types from the equation all together, document the requirements (as "concepts"), and use what amounts to duck typing. This fits well a policy of compile-time polymorphism.
Perhaps a midground would be to create a template function which statically checks its conditions at instantiation. Here's a sketch (which I don't guarantee will compile).
class shareable {...};
class seekable {...};
template <typename StreamType>
void needs_sharable_and_seekable(const StreamType& stream)
{
BOOST_STATIC_ASSERT(boost::is_base_and_derived<shareable, StreamType>::value);
BOOST_STATIC_ASSERT(boost::is_base_and_derived<seekable, StreamType>::value);
....
}
Edit: Spent a few minutes making sure things compiled, and "cleaning up" the error messages:
#include <boost/type_traits/is_base_and_derived.hpp>
#include <boost/mpl/assert.hpp>
class shareable {};
class seekable {};
class both : public shareable, public seekable
{
};
template <typename StreamType>
void dosomething(const StreamType& dummy)
{
BOOST_MPL_ASSERT_MSG((boost::is_base_and_derived<shareable, StreamType>::value),
dosomething_requires_shareable_stream,
(StreamType));
BOOST_MPL_ASSERT_MSG((boost::is_base_and_derived<seekable, StreamType>::value),
dosomething_requires_seekable_stream,
(StreamType));
}
int main()
{
both b;
shareable s1;
seekable s2;
dosomething(b);
dosomething(s1);
dosomething(s2);
}
Take a look at boost::enable_if
// Before
template <class Stream>
some_type some_function(const Stream& c);
// After
template <class Stream>
boost::enable_if<
boost::mpl::and_<
boost::is_base_and_derived<Shareable,Stream>,
boost::is_base_and_derived<Seekable,Stream>
>,
some_type
>
some_function(const Stream& c);
Thanks to SFINAE this function will only be considered if Stream satisfies the requirement, ie here derive from both Shareable and Seekable.
How about using a template method?
template <typename STREAM>
void doSomething(STREAM &stream)
{
stream.share();
stream.seek(...);
}
You might want the Decorator pattern.
Assuming both Seekable and Shareable have common ancestor, one way I can think of is trying to downcast (of course, asserts replaced with your error-checking):
void foo(Stream *s) {
assert(s != NULL);
assert(dynamic_cast<Seekable*>(s) != NULL);
assert(dynamic_cast<Shareable*>(s) != NULL);
}
Replace 'shareable' and 'seekable' with 'in' and 'out' and find your 'io' solution. In a library similar problems should have similar solutions.

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.