Templates and copy constructor

  • Thread starter Matthias Spiller
  • Start date
M

Matthias Spiller

Hi,

following problem. I'm writing an Image class and want to use templates:

....
template<class TType, int TLayers>
class Image
{
public:
Image();

Image(std::string filename);
....

Where TType stands for int, char aso and TLayers for Grey, RGB aso.

Now, converting Images from one type to another should be possible by
using the copy constructor:

Image<short, RGB> i("blub.jpg");
Image<double, Grey> j(i);

So, I'm trying to declare the copy contructor as follows:

template<class UType, int ULayers>
Image(const Image<UType, ULayers> &img);

and implement it:

template<class UType, int ULayers>
Image<unsigned char, Grey>::Image(const Image<UType, Ulayers> &img)
{
...
};


But at compile time I get the following error:
error: no `Image<unsigned char, 1>::Image(const Image<UType, ULayers>&)'
member function declared in class `Image<unsigned char, 1>'
error: invalid function declaration



Any ideas?

Cheers

matspi
 
R

Rolf Magnus

Matthias said:
Hi,

following problem. I'm writing an Image class and want to use templates:

...
template<class TType, int TLayers>
class Image
{
public:
Image();

Image(std::string filename);
...

Where TType stands for int, char aso and TLayers for Grey, RGB aso.

Now, converting Images from one type to another should be possible by
using the copy constructor:

Image<short, RGB> i("blub.jpg");
Image<double, Grey> j(i);

This wouldn't use a copy constructor.
So, I'm trying to declare the copy contructor as follows:

template<class UType, int ULayers>
Image(const Image<UType, ULayers> &img);

It's not a copy constructor, but a conversion constructor from one template
instance to another.
and implement it:

template<class UType, int ULayers>
Image<unsigned char, Grey>::Image(const Image<UType, Ulayers> &img)
{
...
};

This is a specialization. Do you have a class definition for the
specialization Image<unsigned char, Grey>?

Maybe you wanted:

template<class TType, int TLayers>
template<class UType, int ULayers>
Image<TType, TLayers>::Image(const Image<UType, ULayers> &img)
{
//...
}
 
M

Matthias Spiller

This is a specialization. Do you have a class definition for the
specialization Image<unsigned char, Grey>?

Maybe you wanted:

template<class TType, int TLayers>
template<class UType, int ULayers>
Image<TType, TLayers>::Image(const Image<UType, ULayers> &img)
{
//...
}

No, I don't have a definition for the specialization. How would this be
done?

I need a different constructor for each "destination" class. So do I
have to define each class seperatly?

Image<unsigned char, Grey>
Image<short, Grey>
Image<float, Grey>
....


Thank you

Matthias
 
R

Rolf Magnus

Matthias said:
No, I don't have a definition for the specialization. How would this be
done?

If you want to specialize a member of a template class, you have to
specialize the whole class. Something like:

template<>
class Image<unsigned char, Grey>
{
public:
template<class UType, int ULayers>
Image(const Image<UType, ULayers> &img);
//... the other members
};

template<>
template<class UType, int ULayers>
Image<unsigned char, int>::Image(const Image<UType, ULayers> &img)
{
//...
}

I need a different constructor for each "destination" class. So do I
have to define each class seperatly?

Yes. If you have common code, you can put it into a base class, or you can
write non-member functions, specialize them and call them from your class
members if you want to avoid specializing the class.
 
M

Me

No, I don't have a definition for the specialization. How would this be
done?

I need a different constructor for each "destination" class. So do I
have to define each class seperatly?

Image<unsigned char, Grey>
Image<short, Grey>
Image<float, Grey>

What you should do is define it once but use an adaptor function/class
(check out http://antigrain.com for a real-world example of how
somebody coded that up) to do all the work (I'm assuming you're copying
a 2d array of values from image to the other), like this (not sure if
this compiles, but you get the idea):

template<>
inline void convert<Grey, Grey>(unsigned char * &dest, const float *
&src)
{
*dest++ = clamp(0.0f, 255.0f, 255.0f * *src++);
}

template<>
inline void convert<Grey, RGB>(unsigned char * &dest, const float *
&src)
{
*dest++ = /*some formula involving src[0..2]*/;
src += 3;
}

etc.

template<class TType, int TLayers>
template<class UType, int ULayers>
Image<TType, TLayers>::Image(const Image<UTyle, ULayers> &img)
{
data = alloc(whatever);

for (size_t y = 0; y < height; ++y) {
TType *src = data(y);
UType *dest = img.data(y);
for (size_t x = 0; x < width; ++x) {
convert<TType, UType>(src, dest);
}
}
}

Personally, I wouldn't put that code directly in a constructor, I would
put it in a separate member function, that way it can be called at any
time. You can build a constructor that calls it if you want (but make
sure to mark it with 'explicit'). I'd recommend not making it a
constructor because it's hard to grep for and if you implement
copy-on-write to share images and change typedefs around later, code
that used to just do a refcount turns into an expensive conversion copy
that may throw an exception.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top