Added Source and Sink Template Classes to DKit
Today I wanted to add a little bit more to DKit, so I decided that the next best thing to add were the concepts of a template source and sink. When I built the MessageSource and MessageSink back at PEAK6, I did it in the context of a Message object. That was fine, because that's all we needed, but this time I wanted to make it a little better - no a lot better, so I made the source and sink template classes.
This will allow me to use the pointers like I did before, but it will also make it very easy to use integers, or doubles - or anything. This will be a far better solution to the problem than a fixed class, or pointer to a class.
The only real problem I ran into - if there was indeed any real problems, was the syntax for specifying the template class methods in the implementation file. The header was pretty clear and straight forward, but the implementation was a bit trickier.
Thankfully, I was able to find some examples on the web, but the syntax was pretty bad. I mean really bad. For example, let's say I had the following template class:
namespace dkit { template <class T> class source { public: virtual void setName( const std::string & aName ); virtual const std::string & getName() const; virtual bool addToListeners( sink<T> *aSink ); }; } // end of namespace dkit
then the implementation file would have to look something like this:
namespace dkit { template <class T> void source<T>::setName( const std::string & aName ) { boost::detail::spinlock::scoped_lock lock(mMutex); mName = aName; } template <class T> const std::string & source<T>::getName() const { return mName; } template <class T> bool source<T>::addToListeners( sink<T> *aSink ) { bool added = false; // first, make sure there's something to do if (aSink != NULL) { // next, see if we can add us as a source to him if (aSink->addToSources(this)) { // finally, make sure we can add him to us added = addToSinks(aSink); } } return added; } } // end of namespace dkit
Now I understand the need to clearly identify the class - hence the template <class T> on the front, but then it seems to really go overboard there. While I'm sure there's a wonderful reason for all this, it seems to have not undergone any simplification over the years. That's probably part of the problem that folks have with C++ - it's complicated looking. And if you don't get it just right, you're not going to even get it to compile.
But for me, it's just what has to be done in order to have template programming. It's a pain, yes, but it's so incredibly worth it.