Re: virtual function template workaround
On Mar 21, 3:18 pm, "Emmanuel Deloget" <log...@free.fr> wrote:
On 19 mar, 20:17, "pl" <patrick...@hotmail.com> wrote:
Shouldn't that be a dynamic_cast<>? As I understand the code, you're
upcasting an instance - so static_cast<> is probably not the right way
to do it.
I have better luck with static_cast when upcasting. Also, you don't
have the RTTI overhead that dynamic_cast gives you. The compile-time
requirements are more stringent, but it keeps you from getting a NULL
pointer.
The problem with calling the function from the template parameter is
that you are statically bound to that specialization.
data_access_base requires a template parameter, and in no situation
will the same specialization call a different function. Additionally,
virtual functions are really meant for pointers of an unknown
underlying type, but a pointer to data_access_base <T> will always
call T->read().
I dealt with this problem for a year or so and ended up coming up with
a base class registration lib. This would register pointers to
wrapped static_cast calls and required a lot of void*. Needless to
say that was entirely the wrong way to go.
What I would do if I were you is design a wrapper like you might for a
functor. Make an abstract class which holds the required interface
(i.e. ++, --, *, ->, etc.) Next, make a template derivative of that
class which holds any iterator and implements each of the operators
simply by calling it on that encapsulated iterator. Next, make a
class that holds a dynamic instance of the abstract class that
constructs with an iterator, making an internal instance of the
template implementation.
After you have the third class, make the function 'read' take a copy
as its argument. To call the function create an instance of the third
class above using the iterator and provide it as an argument.
//base class: generic iterator
interface________________________________________
template <class Type>
struct iterator_wrapper_base
{
virtual iterator_wrapper_base &operator ++ () = 0;
virtual Type &operator * () = 0;
virtual ~iterator_wrapper_base() {}
};
//template class: specific iterator
implementation______________________________
template <class Type, class Iterator>
struct iterator_wrapper_template :
public iterator_wrapper_base <Type>
{
iterator_wrapper_template(Iterator iIter) : iterator(iIter) {}
iterator_wrapper_base <Type> &operator ++ ()
{
++iterator;
return *this;
}
Type &operator * ()
{ return *iterator; }
virtual ~iterator_wrapper_template() {}
private:
Iterator iterator;
};
//final class: dynamic iterator
storage_________________________________________
template <class Type>
struct iterator_wrapper_final :
public iterator_wrapper_base <Type>
{
template <class Iterator>
iterator_wrapper_final(Iterator iIter) :
instance(new iterator_wrapper_template <Type, Iterator> (iIter)) {}
//... add copy constructor ...
//... add assignment operator ...
iterator_wrapper_base <Type> &operator ++ ()
{
++(*instance);
return *this;
}
Type &operator * ()
{ return *(*instance); }
~iterator_wrapper_final()
{ delete instance; }
private:
iterator_wrapper_base <Type> *instance;
};
//YOUR
CLASS____________________________________________________________________
struct concrete_data_access
{
virtual void read(iterator_wrapper_final <int> iIter)
{
++iIter;
*iIter = 0;
}
};
//
main__________________________________________________________________________
int main()
{
int array[100];
int *dynamic = new int[100];
concrete_data_access test_access;
test_access.read(iterator_wrapper_final <int> (array));
test_access.read(iterator_wrapper_final <int> (dynamic));
delete dynamic;
}
The postfix operators might be a slight problem, but could be easily
worked around by returning iterator_wrapper_final.
Kevin P. Barry
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]