Accessing the function pointer type of the base template classes
I have a class that was provided that I really don't want to change, but I want to extend it. I am a template model and newbie experimenting with a Decorator pattern applied to a template class. The template class contains a member pointer (if I understand the semantics correctly) in another class. Pointer-to-member is an XML stream deserializer. Type "T" is the type of XML document to be deserialized.
template <typename T> class B {
public:
typedef std::auto_ptr<T> MYFUN(
std::istream&, const std::string&, const std::string& );
public:
B<T>( MYFUN* p );
private:
MYFUN *fptr;
std::string aString1;
std::string aString2;
};
The typedef looks strange to me after reading http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5 and still this class works fine as it is. There are no additional #defines in the provided header file, so this is a bit cryptic to me.
Now I'm trying to extend it like Decorator because I want to do a little work on the auto_ptr object returned by MYFUN:
template <typename T>
class D : public class B<T>
{
D( B<T>::MYFUN *fPtr, B<T> *providedBase ); //compiler complaint
//Looks like B
private:
B* base_;
};
template <typename T>
D<T>::D( B<T>::MYFUN *p, B<T> *base ) //compiler complaint
:
B<T>::B( p ), base_(providedBase)
{ }
When trying to compile this, I get a syntax complaint on the two lines mentioned. An error is something like "expected") "at *". There is no complaint that MYFUN is undefined.
When I override an element pointer in D with the same signature as in D, i.e.
//change MYFUN to NEWFUN in D)
typedef std::auto_ptr<T> MYNEWFUN(
std::istream&, const std::string&, const std::string& );
It works. I prefer not to do this for every D / Decorator I can make from B. I tried to typedef more globally but couldn't get the syntax on the right because of the undefined template parameter.
a source to share
The compilation error is due to the fact that the compiler cannot tell what you are talking about the type.
Try:
D( typename B<T>::MYFUN *fPtr, B<T> *providedBase );
and
template <typename T>
D<T>::D( typename B<T>::MYFUN *p, B<T> *base )
See the Templates section in the C ++ FAQ Lite for more details on why this is needed, but the summary is that due to the possibility of template specialization, the compiler cannot be sure what is B<T>::MYFUN
actually referring to a type.
a source to share
The definition of MYPUN typedef in B is done with private visibility. D won't be able to access it. If you change it to protected or open, does it work?
template <typename T> class B {
protected:
typedef std::auto_ptr<T> MYFUN(
std::istream&, const std::string&, const std::string& );
...
};
a source to share
The problem I see with this is that B :: MYFUN is a private typedef.
Hence, any inheriting class cannot access it.
Change this to:
template <typename T> class B
{
public:
typedef std::auto_ptr<T> MYFUN( std::istream&, const std::string&, const std::string& );
public:
B<T>( MYFUN* p );
private:
MYFUN *fptr;
std::string aString1;
std::string aString2;
};
a source to share