I have a class that I’ve been provided that I really don’t want to change, but I do want to extend. I’m a pattern and template newbie experimenting with a Decorator pattern applied to a template class. Template class contains a pointer-to-member (if I understand the semantics correctly) in yet another class. The pointer-to-member is the deserializer of an XML istream. The 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 odd to me after reading http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5, and yet this class seems to work fine as-is. There aren’t any additional #defines in the provided header file, so this is a little mysterious to me.
Now I try to extend it, as Decorator because I want to do a bit more 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 at the two lines shown. Error is something like “expected ‘)’ at *”. There is no complaint about MYFUN being undefined.
When I re-define the pointer-to-member 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& );
This works. I prefer not to have to do this for every D/Decorator I might make of B. I tried to perform the typedef more globally, but couldn’t get the syntax right due to the template parameter being undefined.
The compile error is due to the fact that the compiler can’t tell you are talking about a type.
Try:
and
See: the templates section of the C++ FAQ Lite for more details on why this is necessary, but the summary is that because of the possibility of template specialization, there is no way for the compiler to be sure that
B<T>::MYFUNis actually referring to a type.