By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,374 Members | 1,768 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,374 IT Pros & Developers. It's quick & easy.

template and virtual

P: n/a
Sometimes - more often than I would like - I run into situations
where I need a member function to be simultaneously templated and
virtual. I know it can be done, but I'm wondering if there's
some clever design trick that can circumvent this problem.

Example:

template <class Pixel_t>
class Image;

class BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // draw self onto image.

};

class Circle : public BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // circle specific.
};

etc.

I have a

list<BaseShape*Shapes;

which I draw in a sweep:

list<BaseShape*>::iterator s;
for(s=Shapes.begin(); s!=Shapes.end(); s++)
s->draw(I);

This requires that draw() be virtual. Note that nothing else
but draw() needs to know anything about the pixel type (the
template parameter of Image), so I don't want to make the entire
BaseImage a template. Also, since Image is templated, I can't
derive all Images from one NON-templated common, abstract
BaseImage (and define a virtual void draw(BaseImage & I) const =0).
Is there any way to do what I want? I suspect there may be some
design flaw, otherwise I wouldn't be getting to this problem,
but I really like the idea of having each shape draw itself on
the image. If only the image was of a single type.
Sep 22 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Amadeus W. M. wrote:
Sometimes - more often than I would like - I run into situations
where I need a member function to be simultaneously templated and
virtual. I know it can be done, but I'm wondering if there's
some clever design trick that can circumvent this problem.

Example:

template <class Pixel_t>
class Image;

class BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // draw self onto image.

};

class Circle : public BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // circle specific.
};

etc.

I have a

list<BaseShape*Shapes;

which I draw in a sweep:

list<BaseShape*>::iterator s;
for(s=Shapes.begin(); s!=Shapes.end(); s++)
s->draw(I);
What is 'I'? How is it declared/defined?
This requires that draw() be virtual. Note that nothing else
but draw() needs to know anything about the pixel type (the
template parameter of Image), so I don't want to make the entire
BaseImage a template. Also, since Image is templated, I can't
derive all Images from one NON-templated common, abstract
BaseImage (and define a virtual void draw(BaseImage & I) const =0).
Is there any way to do what I want? I suspect there may be some
design flaw, otherwise I wouldn't be getting to this problem,
but I really like the idea of having each shape draw itself on
the image. If only the image was of a single type.
Flaws? You need flaws? We're gonna give you flaws! :-)

Just kiddin'.

Well, the major flaw is that you're trying to make shapes aware of
the pixel format (at least that's how I understand your desire to
parameterize on 'Pixel_t'. So, what happens if 'Circle' doesn't
provide a definition of its 'draw' member for some 'Pixel_t'? What
does it draw? Who draws?

It seems that a better solution would be to provide an abstract
type for what you have as 'Image' and let every 'Shape' use some
interface to reach at those "pixels" (what if you need a vector
format? what then? anyway...) So, I think that the "flaw" is in
*incompleteness* of your design.

I strongly recommend asking in 'comp.graphics.algorithms' and in
'comp.object' for a better OOP solution. Then come back and we'll
help you put into C++ terms.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 22 '06 #2

P: n/a
On Fri, 22 Sep 2006 08:52:31 -0400, Victor Bazarov wrote:
Amadeus W. M. wrote:
>Sometimes - more often than I would like - I run into situations
where I need a member function to be simultaneously templated and
virtual. I know it can be done, but I'm wondering if there's
some clever design trick that can circumvent this problem.

Example:

template <class Pixel_t>
class Image;

class BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // draw self onto image.

};

class Circle : public BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // circle specific.
};

etc.

I have a

list<BaseShape*Shapes;

which I draw in a sweep:

list<BaseShape*>::iterator s;
for(s=Shapes.begin(); s!=Shapes.end(); s++)
s->draw(I);

What is 'I'? How is it declared/defined?
I is the image the shape is drawing itself on:

template <class Pixel_t>
Image I;

and in BaseShape,

template <class Pixel_t>
void draw(Image<Pixel_t& I);

>
>This requires that draw() be virtual. Note that nothing else
but draw() needs to know anything about the pixel type (the
template parameter of Image), so I don't want to make the entire
BaseImage a template. Also, since Image is templated, I can't
derive all Images from one NON-templated common, abstract
BaseImage (and define a virtual void draw(BaseImage & I) const =0).
Is there any way to do what I want? I suspect there may be some
design flaw, otherwise I wouldn't be getting to this problem,
but I really like the idea of having each shape draw itself on
the image. If only the image was of a single type.

Flaws? You need flaws? We're gonna give you flaws! :-)

Just kiddin'.

Well, the major flaw is that you're trying to make shapes aware of
the pixel format (at least that's how I understand your desire to
parameterize on 'Pixel_t'.
I was trying to do exactly the opposite. The drawing _should_ be
independent of the pixel format. However, the Image class is
already templated by Pixel_t, so I have no choice but make
BaseShape::draw() templated.
So, what happens if 'Circle' doesn't
provide a definition of its 'draw' member for some 'Pixel_t'? What
does it draw? Who draws?

It seems that a better solution would be to provide an abstract
type for what you have as 'Image' and let every 'Shape' use some
interface to reach at those "pixels" (what if you need a vector
format? what then? anyway...) So, I think that the "flaw" is in
*incompleteness* of your design.

I strongly recommend asking in 'comp.graphics.algorithms' and in
'comp.object' for a better OOP solution. Then come back and we'll
help you put into C++ terms.

V
Sep 22 '06 #3

P: n/a

Amadeus W. M. wrote:
Sometimes - more often than I would like - I run into situations
where I need a member function to be simultaneously templated and
virtual. I know it can be done,
You're wrong...it can't be done. A templated member can not be
virtual...it is a language requirement that they not be both. Granted,
there are cases when it would be nice but it can't be done so you have
to come up with some other way to do what you need to do.

Sep 22 '06 #4

P: n/a
Amadeus W. M. wrote:
On Fri, 22 Sep 2006 08:52:31 -0400, Victor Bazarov wrote:
>Amadeus W. M. wrote:
>>Sometimes - more often than I would like - I run into situations
where I need a member function to be simultaneously templated and
virtual. I know it can be done, but I'm wondering if there's
some clever design trick that can circumvent this problem.

Example:

template <class Pixel_t>
class Image;

class BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // draw self onto image.

};

class Circle : public BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // circle specific.
};

etc.

I have a

list<BaseShape*Shapes;

which I draw in a sweep:

list<BaseShape*>::iterator s;
for(s=Shapes.begin(); s!=Shapes.end(); s++)
s->draw(I);

What is 'I'? How is it declared/defined?

I is the image the shape is drawing itself on:

template <class Pixel_t>
Image I;
That's a syntax error. Try not to avoid answering the question.
and in BaseShape,

template <class Pixel_t>
void draw(Image<Pixel_t& I);
That's a declaration. It all depends on what 'Pixel_t' is. It
can be 'int' for all I know. So, the question remains: in your
code when you write

s->draw(I);

WTF is 'I'? When you "draw in a sweep", is that part of concrete
code or is it part of another template? Where does it become real?
It has to, at some point, right? Show us.
>>This requires that draw() be virtual. Note that nothing else
but draw() needs to know anything about the pixel type (the
template parameter of Image), so I don't want to make the entire
BaseImage a template. Also, since Image is templated, I can't
derive all Images from one NON-templated common, abstract
BaseImage (and define a virtual void draw(BaseImage & I) const =0).
Is there any way to do what I want? I suspect there may be some
design flaw, otherwise I wouldn't be getting to this problem,
but I really like the idea of having each shape draw itself on
the image. If only the image was of a single type.

Flaws? You need flaws? We're gonna give you flaws! :-)

Just kiddin'.

Well, the major flaw is that you're trying to make shapes aware of
the pixel format (at least that's how I understand your desire to
parameterize on 'Pixel_t'.

I was trying to do exactly the opposite. The drawing _should_ be
independent of the pixel format.
Then show what your 'draw' looks like.
However, the Image class is
already templated by Pixel_t, so I have no choice but make
BaseShape::draw() templated.
Yes, you do. Whose class is 'Image'? Rewrite it so it has some
base class. Then pass the reference to that base class to your
'draw' function instead of a concrete type 'Image<Pixel_t>'.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 22 '06 #5

P: n/a
On Fri, 22 Sep 2006 08:43:21 -0700, Noah Roberts wrote:
>
Amadeus W. M. wrote:
>Sometimes - more often than I would like - I run into situations
where I need a member function to be simultaneously templated and
virtual. I know it can be done,

You're wrong...it can't be done. A templated member can not be
virtual...it is a language requirement that they not be both. Granted,
there are cases when it would be nice but it can't be done so you have
to come up with some other way to do what you need to do.
It was a typo. Of course it can't be done, hence the post, to
see if there was any way around it.

Sep 22 '06 #6

P: n/a

Amadeus W. M. wrote:
Sometimes - more often than I would like - I run into situations
where I need a member function to be simultaneously templated and
virtual. I know it can be done, but I'm wondering if there's
some clever design trick that can circumvent this problem.

Example:

template <class Pixel_t>
class Image;

class BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // draw self onto image.

};

class Circle : public BaseShape
{
public:

template <class Pixel_t>
void draw(Image<Pixel_t& I); // circle specific.
};

etc.

I have a

list<BaseShape*Shapes;

which I draw in a sweep:

list<BaseShape*>::iterator s;
for(s=Shapes.begin(); s!=Shapes.end(); s++)
s->draw(I);

This requires that draw() be virtual. Note that nothing else
but draw() needs to know anything about the pixel type (the
template parameter of Image), so I don't want to make the entire
BaseImage a template. Also, since Image is templated, I can't
derive all Images from one NON-templated common, abstract
BaseImage (and define a virtual void draw(BaseImage & I) const =0).
Is there any way to do what I want? I suspect there may be some
design flaw, otherwise I wouldn't be getting to this problem,
but I really like the idea of having each shape draw itself on
the image. If only the image was of a single type.
Not discussing the design there might be a possible solution involving
static typed interfaces. Is more clumsy and maybe doesn't offer all the
flexibility you need but has obvious avantages. Here is some quickly
assembled code:

class Pixel{};

template <class Pixel_t>
class Image
{};

template <class PIXEL>
class IShape
{
typedef void (*FP1)(void* , Image<PIXEL>&);
public:
template <class T>
IShape(T& x)
: p_(&x),
pf1_(&functions<T>::draw)
{}
void draw(Image<PIXEL>& i)
{
pf1_(p_, i);
}
private:
template <class TT>
struct functions
{
static void draw( void* a, Image<PIXEL>& w )
{
static_cast<TT*>(a)->draw(w);
}
};

private:
void* p_;
FP1 pf1_;
};

struct BaseShape
{};

struct Circle : BaseShape
{
public:
template <class Pixel_t>
void draw(Image<Pixel_t& I)
{
std::cout << "circle specific. \n";
}
};
struct Square : BaseShape
{
public:
template <class Pixel_t>
void draw(Image<Pixel_t& I)
{
std::cout << "square specific. \n";
}
};

template <class T>
struct BaseShapeIterator
{
void draw(Image<T>& img)
{
for(typename std::vector<IShape<T::iterator i =
v.begin(); i != v.end(); ++i)
{
i->draw(img);
}
}
template <class S>
void append( S& s)
{
v.push_back(IShape<T>(s));
}
private:
std::vector<IShape<T v;
};

void test()
{
Circle c;
Square s;
BaseShapeIterator<Pixelb;
b.append(c);
b.append(s);
Image<Pixelimg;
b.draw(img);
}
HTH
Radu

Sep 22 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.