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

Templates and copy constructor

P: n/a
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
Jul 23 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Matthias Spiller wrote:
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)
{
//...
}

Jul 23 '05 #2

P: n/a



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
Jul 23 '05 #3

P: n/a
Matthias Spiller wrote:



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?


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.
Image<unsigned char, Grey>
Image<short, Grey>
Image<float, Grey>
...
Thank you

Matthias


Jul 23 '05 #4

P: n/a
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.

Jul 23 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.