Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Alternative pattern for virtual template

Reply
Thread Tools

Alternative pattern for virtual template

 
 
GeeRay
Guest
Posts: n/a
 
      05-05-2009
Hi all,
I have this problem: I need to implement a class hierarchy where the
main class has a template method that will be inherited by the subclass.
Something like:

class SuperClass
{
public:
template<typename T>
virtual void foo(const T& t) const = 0;
}


class SubClass: public SuperClass
{
public:
template<typename T>
virtual void foo(const T& t) const { cout << t << endl;}
}

Considering I know why it is not possible to make a template virtual, is
there an alternative pattern to solve this kind of problems.

Thanks in advance
 
Reply With Quote
 
 
 
 
Neelesh
Guest
Posts: n/a
 
      05-05-2009
On May 5, 6:17*pm, GeeRay <a...@a.a> wrote:
> Hi all,
> * * * * I have this problem: I need to implement a class hierarchy where the
> main class has a template method that will be inherited by the subclass.
> Something like:
>
> class SuperClass
> {
> public:
> * * * * template<typename T>
> * * * * virtual void foo(const T& t) const = 0;
>
> }
>
> class SubClass: public SuperClass
> {
> public:
> * * * * template<typename T>
> * * * * virtual void foo(const T& t) const { cout << t << endl;}
>
> }
>
> Considering I know why it is not possible to make a template virtual, is
> there an alternative pattern to solve this kind of problems.
>
> Thanks in advance


Making it a class template can solve the problem:

template<class T> class SuperClass
{
public:
virtual void foo(const T& t) const = 0;

};

template<class T> class SubClass: public SuperClass<T>
{
public:
virtual void foo(const T& t) const { cout << t << endl;}
//By the way, "virtual keyword isn't needed here

};

int main()
{
SuperClass<int> *s = new SubClass<int>();
s->foo(10); //prints 10

}
 
Reply With Quote
 
 
 
 
GeeRay
Guest
Posts: n/a
 
      05-05-2009
Neelesh ha scritto:
> On May 5, 6:17 pm, GeeRay <a...@a.a> wrote:
>> Hi all,
>> I have this problem: I need to implement a class hierarchy where the
>> main class has a template method that will be inherited by the subclass.
>> Something like:
>> [...cut...]
>> Thanks in advance

>
> Making it a class template can solve the problem:
>
> template<class T> class SuperClass
> {
> public:
> virtual void foo(const T& t) const = 0;
>
> };
>
> template<class T> class SubClass: public SuperClass<T>
> {
> public:
> virtual void foo(const T& t) const { cout << t << endl;}
> //By the way, "virtual keyword isn't needed here
>
> };
>
> int main()
> {
> SuperClass<int> *s = new SubClass<int>();
> s->foo(10); //prints 10
>
>



The problem is that I would like to use the same method with different
types:

SuperClass * s = new SubClass();
s->foo<int>(2);
s->foo<const char*> ("foo");
 
Reply With Quote
 
Noah Roberts
Guest
Posts: n/a
 
      05-05-2009
GeeRay wrote:
> Hi all,
> I have this problem: I need to implement a class hierarchy where the
> main class has a template method that will be inherited by the subclass.
> Something like:
>
> class SuperClass
> {
> public:
> template<typename T>
> virtual void foo(const T& t) const = 0;
> }
>
>
> class SubClass: public SuperClass
> {
> public:
> template<typename T>
> virtual void foo(const T& t) const { cout << t << endl;}
> }
>
> Considering I know why it is not possible to make a template virtual, is
> there an alternative pattern to solve this kind of problems.


No. There are some things you can do but none of them generate the
equivalent of virtual template functions. Simple fact is that the
language doesn't support such a construct. How could it?

I find that any time I'm tempted to do this, my design is not exactly
correct.

The closest you might come is to use NVPI and account for every possible
argument to your template by hand:

struct Base
{
// Document the concept:
// T must be int or double.
template < typename T >
void f(T const& x);

protected:
virtual void do_f(double const& x) { ... }
virtual void do_f(int const& x) { ... }
};

template < >
void Base::f<double>(double const& x) { do_f(x); }
template < >
void Base::f<int>(int const& x) { do_f(x); }

Basically you're doing what the compiler would have to magically do if
it were to attempt supporting virtual template functions. As you can
see, pretty much impossible without full and future knowledge of all
calls to f<>(), which is why it isn't done.

I'm sure you could make some preprocessor stuff to construct much of the
above code, but you're still going to have to account for all possible
types passed to your function.

I'd suggest looking at alternative approaches.
 
Reply With Quote
 
Martin Eisenberg
Guest
Posts: n/a
 
      05-05-2009
GeeRay wrote:

> class SuperClass
> {
> public:
> template<typename T>
> virtual void foo(const T& t) const = 0;
> }
>
> class SubClass: public SuperClass
> {
> public:
> template<typename T>
> virtual void foo(const T& t) const { cout << t << endl;}
> }
>
> Considering I know why it is not possible to make a template
> virtual, is there an alternative pattern to solve this kind of
> problems.


If your higher-level goal is to ensure that the class does indeed
have a certain function, perhaps you can equip its clients with Boost
Concept Check.


Martin

--
Quidquid latine scriptum est, altum videtur.
 
Reply With Quote
 
Michael Doubez
Guest
Posts: n/a
 
      05-06-2009
On 5 mai, 17:24, Noah Roberts <n...@nowhere.com> wrote:
> GeeRay wrote:
> > Hi all,
> > I have this problem: I need to implement a class hierarchy where the
> > main class has a template method that will be inherited by the subclass.
> > Something like:

>
> > class SuperClass
> > {
> > public:
> > template<typename T>
> > virtual void foo(const T& t) const = 0;
> > }

>
> > class SubClass: public SuperClass
> > {
> > public:
> > template<typename T>
> > virtual void foo(const T& t) const { cout << t << endl;}
> > }

>
> > Considering I know why it is not possible to make a template virtual, is
> > there an alternative pattern to solve this kind of problems.

>
> No. There are some things you can do but none of them generate the
> equivalent of virtual template functions. Simple fact is that the
> language doesn't support such a construct. How could it?
>
> I find that any time I'm tempted to do this, my design is not exactly
> correct.
>
> The closest you might come is to use NVPI and account for every possible
> argument to your template by hand:
>
> struct Base
> {
> // Document the concept:
> // T must be int or double.
> template < typename T >
> void f(T const& x);
>
> protected:
> virtual void do_f(double const& x) { ... }
> virtual void do_f(int const& x) { ... }
>
> };
>
> template < >
> void Base::f<double>(double const& x) { do_f(x); }
> template < >
> void Base::f<int>(int const& x) { do_f(x); }
>
> Basically you're doing what the compiler would have to magically do if
> it were to attempt supporting virtual template functions. As you can
> see, pretty much impossible without full and future knowledge of all
> calls to f<>(), which is why it isn't done.
>
> I'm sure you could make some preprocessor stuff to construct much of the
> above code, but you're still going to have to account for all possible
> types passed to your function.
>
> I'd suggest looking at alternative approaches.


On of this approach is to use dynamic polymorphism, that is if you can
define a same contract on your type. As an example if your foo is only
displaying a message with the data in parameter, your contract if that
the type should support (ostream<<T), you define the interface:

struct foo_ostreamable
{
virtual ostream& output(ostream&)const=0;
};

Then you define a templated foo_streambable implementation:

template<typename T>
struct foo_ostreamable_imp: foo_ostreamable
{
T value;
foo_ostreamable_imp(const T& t):value(t){}

virtual ostream& output(ostream& os)const{return os<<value;}
};

And finally the parameter of SuperClass::foo with templated
constructor:

struct foo_param
{
template<typename T>
foo_param(const T& t){data.reset(new foo_ostreamable_imp<T>(t));

scoped_ptr<foo_ostreamable> data;
};

// foo_param can be written into ostream
ostream& operator<<(ostream& os,const foo_param& p)
{
return p.data->output(os);
}

And finally, you define your classes:
class SuperClass
{
public:
virtual void foo(const foo_param&) const = 0;
};

class SubClass: public SuperClass
{
public:
virtual void foo(const foo_param& p) const { cout << p <<
endl;}
} ;

The compiler will automatically resolve with correct subtype:
SubClass s;
s.foo(1);
s.foo(0.1);
s.foo("bar");
....

If you want to keep/compare foo_param values, there is some management
to do such as deep copy and others to put it into canonical form. If a
type doesn't react as you want, you overload foo_param constructor.

There is an overhead but that depends on what you want.

--
Michael
 
Reply With Quote
 
GeeRay
Guest
Posts: n/a
 
      05-06-2009
Michael Doubez ha scritto:
> On 5 mai, 17:24, Noah Roberts <n...@nowhere.com> wrote:
>> GeeRay wrote:
>>> Hi all,
>>> I have this problem: I need to implement a class hierarchy where the
>>> main class has a template method that will be inherited by the subclass.
>>> Something like:
>>> [cut]

>
> On of this approach is to use dynamic polymorphism, that is if you can
> define a same contract on your type. As an example if your foo is only
> displaying a message with the data in parameter, your contract if that
> the type should support (ostream<<T), you define the interface:
>
> struct foo_ostreamable
> {
> virtual ostream& output(ostream&)const=0;
> };
>
> Then you define a templated foo_streambable implementation:
>
> template<typename T>
> struct foo_ostreamable_imp: foo_ostreamable
> {
> T value;
> foo_ostreamable_imp(const T& t):value(t){}
>
> virtual ostream& output(ostream& os)const{return os<<value;}
> };
>
> And finally the parameter of SuperClass::foo with templated
> constructor:
>
> struct foo_param
> {
> template<typename T>
> foo_param(const T& t){data.reset(new foo_ostreamable_imp<T>(t));
>
> scoped_ptr<foo_ostreamable> data;
> };
>
> // foo_param can be written into ostream
> ostream& operator<<(ostream& os,const foo_param& p)
> {
> return p.data->output(os);
> }
>
> And finally, you define your classes:
> class SuperClass
> {
> public:
> virtual void foo(const foo_param&) const = 0;
> };
>
> class SubClass: public SuperClass
> {
> public:
> virtual void foo(const foo_param& p) const { cout << p <<
> endl;}
> } ;
>
> The compiler will automatically resolve with correct subtype:
> SubClass s;
> s.foo(1);
> s.foo(0.1);
> s.foo("bar");
> ...
>
> If you want to keep/compare foo_param values, there is some management
> to do such as deep copy and others to put it into canonical form. If a
> type doesn't react as you want, you overload foo_param constructor.
>
> There is an overhead but that depends on what you want.
>
> --
> Michael


You're great!
Thank you very much, that's exactly what I was looking for.

-GR
 
Reply With Quote
 
DerTopper@web.de
Guest
Posts: n/a
 
      05-06-2009
Michael Doubez schrieb:
[snipped original problem about the problem of combining virtual
methods with templates]

> On of this approach is to use dynamic polymorphism, that is if you can
> define a same contract on your type. As an example if your foo is only
> displaying a message with the data in parameter, your contract if that
> the type should support (ostream<<T), you define the interface:
>
> struct foo_ostreamable
> {
> virtual ostream& output(ostream&)const=0;
> };
>
> Then you define a templated foo_streambable implementation:
>
> template<typename T>
> struct foo_ostreamable_imp: foo_ostreamable
> {
> T value;
> foo_ostreamable_imp(const T& t):value(t){}
>
> virtual ostream& output(ostream& os)const{return os<<value;}
> };
>
> And finally the parameter of SuperClass::foo with templated
> constructor:
>
> struct foo_param
> {
> template<typename T>
> foo_param(const T& t){data.reset(new foo_ostreamable_imp<T>(t));
>
> scoped_ptr<foo_ostreamable> data;
> };
>
> // foo_param can be written into ostream
> ostream& operator<<(ostream& os,const foo_param& p)
> {
> return p.data->output(os);
> }
>
> And finally, you define your classes:
> class SuperClass
> {
> public:
> virtual void foo(const foo_param&) const = 0;
> };
>
> class SubClass: public SuperClass
> {
> public:
> virtual void foo(const foo_param& p) const { cout << p <<
> endl;}
> } ;
>
> The compiler will automatically resolve with correct subtype:
> SubClass s;
> s.foo(1);
> s.foo(0.1);
> s.foo("bar");
> ...
>
> If you want to keep/compare foo_param values, there is some management
> to do such as deep copy and others to put it into canonical form. If a
> type doesn't react as you want, you overload foo_param constructor.
>
> There is an overhead but that depends on what you want.
>
> --
> Michael


That's a good explanation. Is this pattern named already?

Stuart
 
Reply With Quote
 
Michael Doubez
Guest
Posts: n/a
 
      05-06-2009
On 6 mai, 14:56, DerTop...@web.de wrote:
> Michael Doubez schrieb:
> [snipped original problem about the problem of combining virtual
> methods with templates]
>
>
>
> > On of this approach is to use dynamic polymorphism, that is if you can
> > define a same contract on your type. As an example if your foo is only
> > displaying a message with the data in parameter, your contract if that
> > the type should support (ostream<<T), you define the interface:

>
> > struct foo_ostreamable
> > {
> > virtual ostream& output(ostream&)const=0;
> > };

>
> > Then you define a templated foo_streambable implementation:

>
> > template<typename T>
> > struct foo_ostreamable_imp: foo_ostreamable
> > {
> > T value;
> > foo_ostreamable_imp(const T& t):value(t){}

>
> > virtual ostream& output(ostream& os)const{return os<<value;}
> > };

>
> > And finally the parameter of SuperClass::foo with templated
> > constructor:

>
> > struct foo_param
> > {
> > template<typename T>
> > foo_param(const T& t){data.reset(new foo_ostreamable_imp<T>(t));

>
> > scoped_ptr<foo_ostreamable> data;
> > };

>
> > // foo_param can be written into ostream
> > ostream& operator<<(ostream& os,const foo_param& p)
> > {
> > return p.data->output(os);
> > }

>
> > And finally, you define your classes:
> > class SuperClass
> > {
> > public:
> > virtual void foo(const foo_param&) const = 0;
> > };

>
> > class SubClass: public SuperClass
> > {
> > public:
> > virtual void foo(const foo_param& p) const { cout << p <<
> > endl;}
> > } ;

>
> > The compiler will automatically resolve with correct subtype:
> > SubClass s;
> > s.foo(1);
> > s.foo(0.1);
> > s.foo("bar");
> > ...

>
> > If you want to keep/compare foo_param values, there is some management
> > to do such as deep copy and others to put it into canonical form. If a
> > type doesn't react as you want, you overload foo_param constructor.

>
> > There is an overhead but that depends on what you want.

>
> > --
> > Michael

>
> That's a good explanation. Is this pattern named already?


I think it is type erasure. It can be useful if you want virtual
member function that takes any iterator of a given kind (let say an
output iterator, it is easier to implement ) but are not too focused
on performances (an indirection plus a virtual call per call, an
allocation per copy , dynamic cast for comparison ...).

The idea is taken from an article in Overload published by ACCU:
http://accu.org/index.php/overloadonline

I don't remember which issue (around end of year 2007 IIRC)

--
Michael

 
Reply With Quote
 
DerTopper@web.de
Guest
Posts: n/a
 
      05-06-2009
Michael Doubez wrote:
> The idea is taken from an article in Overload published by ACCU:
> http://accu.org/index.php/overloadonline
>
> I don't remember which issue (around end of year 2007 IIRC)


Thanks again. Never heard of ACCU (I tried to look up what ACCU means,
but their homepage doesn't say anything about this acronym).

It seems that today is full of surprises (always a new thing to learn
out there). Unfortunately, I can't access any articles on this page
(it looks a bit amateurishly to me).

Stuart
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
alternative for virtual template function? Markus Dehmann C++ 4 07-25-2008 01:07 PM
Non-template class from a template base class with pure virtual methods vilarneto@gmail.com C++ 2 03-25-2007 08:19 PM
Virtual Template or Template Virtual pocmatos@gmail.com C++ 4 01-23-2006 08:44 PM
Quicktime Alternative, RealPlayer Alternative & Media Player Classic John Capleton Computer Support 3 12-05-2005 07:41 AM
virtual template and virtual access for ADSL circuits Gary Cisco 1 04-28-2005 07:26 PM



Advertisments