Jump to content
  • Advertisement
Sign in to follow this  
sdr-one

pointers to templates

This topic is 3965 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi! I was wondering if there's a way to have a pointer to a templated class without specifying the templates, i.e.
template <class T>
class Image {
...
}

void doSomething(Image* img) {
    img->func();
}

Share this post


Link to post
Share on other sites
Advertisement
Not exactly, but you can do this:
template <class T>
class Image {
...
}

template <class T>
void doSomething(Image<T>* img) {
img->func();
}
// Or if you prefer:
template <class T>
void doSomething(T* img) {
img->func();
}






and then you don't need to specify the template argument when you call doSomething. This is legal:


Image<MyClass> im;
doSomething(im); // Note, you don't need doSomething<MyClass>


Share this post


Link to post
Share on other sites
okay, I've tried it, but it seems to break when linking. More info:

image.h

template <class T = RGBColor, int N = 3, int TexFormat = GL_RGB>
class Image {
public:
Image(int width = 256, int height = 256, T& clearColor = GetBlack<T>());
~Image();

void Clear(T& c = (T)0);
void SetPixel(int i, int j, T& c, int srcMode = BLEND_ONE, int dstMode = BLEND_ZERO);
inline void SetPixel(Point2D& p, T& c, int srcMode = BLEND_ONE, int dstMode = BLEND_ZERO) { SetPixel(p.y(), p.x(), c, srcMode, dstMode); }
inline void SetPixelXY(int x, int y, T& c, int srcMode = BLEND_ONE, int dstMode = BLEND_ZERO) { SetPixel(y, x, c, srcMode, dstMode); }

#define OUTSIDE_RETURN(i, j) if(((i)<0) || ((i)>=m_height) || ((j)<0) || ((j)>=m_width)) return (T)0;
#pragma warning(disable : 4172)
inline T& GetPixel(int i, int j) { OUTSIDE_RETURN(i, j); return m_data[j]; }
inline T& GetPixel(Point2D& p) { OUTSIDE_RETURN(p.y(), p.x()); return m_data[p.y()][p.x()]; }
inline T& GetPixelXY(int x, int y) { OUTSIDE_RETURN(y, x); return m_data[y][x]; }

inline int Height() { return m_height; }
inline int Width() { return m_width; }

inline int GetTexID() { return m_texID; }
void Bind();
private:
int m_width, m_height;
int m_width10, m_height10;
static int m_numTextures;
int m_texID;

T** m_data;
BYTE* m_rawData;
};

typedef Image<RGBColor, 3, GL_RGB> Image2D;
typedef Image<BYTE, 1, GL_LUMINANCE> Image2D_grayscale;



image.cpp

template <class T /*= RGBColor*/, int N /*= 3*/, int TexFormat /*= GL_RGB*/>
Image<T, N, TexFormat>::Image(int width /*= 256*/, int height /*= 256*/, T& clearColor /*= (T)0*/) :
m_width(width), m_height(height),
m_width10(10*width), m_height10(10*height),
m_texID(m_numTextures) {
++m_numTextures;

int index = 0;
m_rawData = new BYTE[width*height*N];
m_data = new RGBColor*[height];
for(int i=0; i<height; ++i) m_data = new T[width];
for(int i=0; i<height; ++i)
for(int j=0; j<width; ++j) {
m_data[j] = clearColor;
for(int ni=0; ni<N; ++ni) m_rawData[index+ni] = (BYTE)clearColor[ni];
index+=N;
}
}

template <class T /*= RGBColor*/, int N /*= 3*/, int TexFormat /*= GL_RGB*/>
Image<T, N, TexFormat>::~Image() {
for(int i=0; i<m_height; ++i) delete[] m_data;
delete[] m_data;
delete[] m_rawData;
}

template <class T /*= RGBColor*/, int N /*= 3*/, int TexFormat /*= GL_RGB*/>
void Image<T, N, TexFormat>::Clear(T& c /*= (T)0*/) {
int index = 0;
for(int i=0; i<m_height; ++i)
for(int j=0; j<m_width; ++j) {
m_data[j] = c;
for(int ni=0; ni<N; ++ni) m_rawData[index+ni] = (BYTE)c[ni];
index+=N;
}
}

template <class T /*= RGBColor*/, int N /*= 3*/, int TexFormat /*= GL_RGB*/>
void Image<T, N, TexFormat>::SetPixel(int i, int j, T& c, int srcMode /*= BLEND_ONE*/, int dstMode /*= BLEND_ZERO*/) {
if((i<0) || (i>=m_height) || (j<0) || (j>=m_width)) return;

T src;
T dst;
double att = 0.0;

src = c;
dst = GetPixel(i, j);

switch(srcMode) {
case BLEND_ZERO: src.Attenuate(0.0, 0.0, 0.0, 0.0); break;
case BLEND_ONE: src.Attenuate(1.0, 1.0, 1.0, 1.0); break;
case BLEND_SRC_ALPHA: src.Attenuate(c.a(), c.a(), c.a(), c.a()); break;
case BLEND_ONE_MINUS_SRC_ALPHA: att = 1.0 - c.a();
src.Attenuate(att, att, att, att); break;
case BLEND_DST_ALPHA: src.Attenuate(dst.a(), dst.a(), dst.a(), dst.a()); break;
case BLEND_ONE_MINUS_DST_ALPHA: att = 1.0 - dst.a();
src.Attenuate(att, att, att, att); break;
/********* source only *********/
case BLEND_DST_COLOR: src.Attenuate(dst.r(), dst.g(), dst.b(), dst.a()); break;
case BLEND_ONE_MINUS_DST_COLOR: src.Attenuate(1.0 - dst.r(), 1.0 - dst.g(), 1.0 - dst.b(), 1.0 - dst.a()); break;
case BLEND_SRC_ALPHA_SATURATE: att = min(c.a(), 1.0 - dst.a());
src.Attenuate(att, att, att, 1.0); break;
}
switch(dstMode) {
case BLEND_ZERO: dst.Attenuate(0.0, 0.0, 0.0, 0.0); break;
case BLEND_ONE: dst.Attenuate(1.0, 1.0, 1.0, 1.0); break;
case BLEND_SRC_ALPHA: dst.Attenuate(c.a(), c.a(), c.a(), c.a()); break;
case BLEND_ONE_MINUS_SRC_ALPHA: att = 1.0 - c.a();
dst.Attenuate(att, att, att, att); break;
case BLEND_DST_ALPHA: dst.Attenuate(dst.a(), dst.a(), dst.a(), dst.a()); break;
case BLEND_ONE_MINUS_DST_ALPHA: att = 1.0 - dst.a();
dst.Attenuate(att, att, att, att); break;
/********* destination only *********/
case BLEND_SRC_COLOR: dst.Attenuate(c.r(), c.g(), c.b(), c.a()); break;
case BLEND_ONE_MINUS_SRC_COLOR: dst.Attenuate(1.0 - c.r(), 1.0 - c.g(), 1.0 - c.b(), 1.0 - c.a()); break;
}

T final(src+dst);
m_data[j] = final;
int index = (i*m_width + j)*N;
for(int ni=0; ni<N; ++ni) m_rawData[index+ni] = (BYTE)final[ni];
}

template <class T /*= RGBColor*/, int N /*= 3*/, int TexFormat /*= GL_RGB*/>
void Image<T, N, TexFormat>::Bind() {
glBindTexture(GL_TEXTURE_2D, m_texID);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

glTexImage2D(GL_TEXTURE_2D, 0, N, m_width, m_height, 0, TexFormat, GL_UNSIGNED_BYTE, m_rawData);
}

template <class T /*= RGBColor*/, int N /*= 3*/, int TexFormat /*= GL_RGB*/>
int Image<T, N, TexFormat>::m_numTextures = 0;



It's for use in things like:


#define SWAP(a, b) { int *tmp; tmp = (a); (a) = (b); (b) = tmp; }

class Line2D : public Shape {
public:
Line2D(int sx, int sy, int ex, int ey) :
m_sx(sx), m_sy(sy), m_ex(ex), m_ey(ey) {}
Line2D(Point2D start, Point2D end) :
m_sx(start.x()), m_sy(start.y()), m_ex(end.x()), m_ey(end.y()) {}

template <class T>
void Draw(T *img, RGBColor& c = WHITE, int srcMode = BLEND_ONE, int dstMode = BLEND_ZERO);
private:
int m_sx, m_sy, m_ex, m_ey;
};



template <class T>
void Geometry::Line2D::Draw(T *img, RGBColor& c /*= WHITE*/, int srcMode /*= BLEND_ONE*/, int dstMode /*= BLEND_ZERO*/) {
int *x0 = &m_sx, *y0 = &m_sy, *x1 = &m_ex, *y1 = &m_ey;
bool steep = abs(*y1 - *y0) > abs(*x1 - *x0);

if(steep) {
SWAP(x0, y0);
SWAP(x1, y1);
}
if(*x0 > *x1) {
SWAP(x0, x1);
SWAP(y0, y1);
}
int deltax = *x1 - *x0;
int deltay = abs(*y1 - *y0);
int error = -(deltax + 1)/2;
int ystep;
int y = *y0;
if(*y0 < *y1) ystep = 1; else ystep = -1;
for(int x = *x0; x <= *x1; ++x) {
if(steep)
img->SetPixel(x, y, c, srcMode, dstMode);
else
img->SetPixel(y, x, c, srcMode, dstMode);
error += deltay;
if(error >= 0) {
y += ystep;
error -= deltax;
}
}
}



Right now, though, it doesn't link.
I fixed the missing Image<RGBColor, 3, GL_RGB>::Image(...) and Image<RGBColor, 3, GL_RGB>::~Image() and the successive missing Image<RGBColor, 3, GL_RGB> methods by redefining everything with template<> Image<RGBColor, 3, GL_RGB>::method (totally defeats the purpose), but I don't feel like rewriting each Figure::Draw to work on different Image templates.

Does anyone have any idea what I'm doing wrong?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!