Hopefully I'll be able to explain this issue. If not, I may just have to post a lot of code. Basically, I've got a base class called 'Log' with virtual methods of writing to a log. I have two descendent classes - ScreenLog and FileLog (with all the same methods). (These methods include writing a std::string to a log, writing a char, a float, a vr_arg, a vector, a list .etc.).

I then have a class called MultiLog (which does not descend from Log), which holds a vector of 'Log *' . When I call writeLog on MultiLog, it iterates through each of the Log * objects inside the vector (which are really ScreenLog and FileLog objects), and calls the respective writeLog function.

My problem is this:

I have 2 functions in both FileLog and ScreenLog, that are templated. They basically call a function in another class that I wrote that will iterate through a vector or list of any type and return a string. This allows me to easily log a vector or list of any kind.
template <class Generic> void writeLog(vector<Generic> & logVector )

{

writeLog ( General::vectorToString( logVector ));

}

template <class Generic> void writeLog(list<Generic> & logList )

{

writeLog ( General::listToString( logList ));

}

The problem is that on Visual studio .net, I am required to add functions on the Log class, otherwise they won't work for MultiLog because it's the Log * that I'm using. however, because the functions are templated, I am unable to create the virtual functions (it complains that template and virtual don't mix). If I don't make them virtual, then instead of calling the appropriate ScreenLog or FileLog functions, it calls the Log one, which doesn't do anything.

The weird thing is, on Sun Studio compiler (solaris), I'm not required to create the functions at all for the Log class, and everything works as designed. (I suspect I'm 'getting lucky' that Sun Studio is letting me get away with something illegal)

Anybody have any ideas on how to make this code work on both compilers?

>I am required to add functions on the Log class
If you want them to be treated polymorphically, yes. But templates can't be virtual, and writeLog is best written as a template. Annoying little impasse, isn't it? :) Whatever will you do? How about moving the template up a level, to a template class at Log and MultiLog instead of template functions within Log? Then you can make writeLog virtual and still have the template parameter Generic from the class template to work with. This offers both the behavioral polymorphism of virtual functions and the type polymorphism of templates.

Doesn't that require Log to be explicitly declared as handling a specific type of data when instantiated? (something I don't want to do).

I was able to get around the issue by having multiLog call the General::vectorToString function and then call the existing
writeLog( std::string) function of the ScreenLog and FileLog instead of calling the writeLog( vector<Generic> ...) functions of ScreenLog and FileLog

(Basically, Log now longer requires the template functions...)

template member functions may not be virtual but often you can get around this by templating a class rather than a member function. The only reason you cant have template member functions is because the compiler would never be able to know the vtable size.

>Doesn't that require Log to be explicitly declared as handling a
>specific type of data when instantiated? (something I don't want to do).
Yes. At this point you choose the lesser of two evils. You can't do what you want because the language is defined not to allow it. You can get around it by using a slightly less convenient syntax at the class level. Is there a legitimate reason for not wanting to use a type instantiation of a template class?

Yes, because I could be writing a vector of strings or a vector of longs or a list of Narue objects all to the same log.

Could you attach your code somewhere? I'm curious about your design for this and what it might be used for.

[Translation: I think your design bites, but admit that there could be valid reasons for what you're doing and want to double check before I inform you ;)]

>Be gentle.
Okay. Both your code and your design are pretty fugly. I kept having traumatic flashbacks to early Java while reading your code. But, I can now see why you're doing what you're doing with the way you backed yourself into a corner like that. ;) What were you planning on using this program for?

These are my libraries that I use for all my programs. Could you provide more specific constructive criticism/improvements other than 'fugly'?

I actually use this code in some pretty important financial messaging applications at work so any useful suggestions you may have would be appreciated.

>Could you provide more specific constructive criticism/improvements other than 'fugly'?
I was hoping to avoid that, but here are my main complaints without delving too deeply into the code.

#ifndef __BASE_CLASS__
#define  __BASE_CLASS__

Two leading underscores are always reserved by the implementation. As such, you shouldn't be surprised if your code mysteriously fails to compile.

You use too many Java conventions for the code to be comfortably read as C++ like the naming conventions and the Java-style interface usage (but it gets better as you go down the list of files), and while it may be old, several parts could be handled with existing libraries, such as Boost, so there's a huge amount of reinventing the wheel.

I'll make the changes regarding the underscores. Could you give me an example of what you mean regarding the java style interface? (Is it that I named my mapping class Properties?)

>Could you give me an example of what you mean regarding the java style interface?
I can give you two: Printable and Identifiable.

This article has been dead for over six months. Start a new discussion instead.