Reputation: 2249
Basically I want to accomplish this Conversion between 2 template types
But I want the assignment operator or copy constructor to be specialised.
For example, I have a color class:
template<typename T = float>
class color
{
public:
T r;
T g;
T b;
T a;
color(T R, T G, T B, T A)
: r(R), g(G), b(B), a(A)
{
}
};
Generally, color components are needed as float
s between 0
and 1
. However, it's often easier to provide the components as numbers between 0
and 255
because that's generally what you get in Photoshop or GIMP.
So, I'd like instances of this class to be able to convert between a float
and an int
type:
color<int> c1(255,234,122,14);
color<float> c2 = c1;
And when it does this, the numbers in c1
are divided by 255
to get the 0
to 1
equivalent.
So I've done this so far:
template<typename U>
color<T>(color<U> c)
: r(c.r/255.0), g(c.g/255.0), b(c.b/255.0), a(c.a/255.0)
{
}
But this would also divide a float
instance by 255 as well. I can't figure out how to specialise this constructor (or assignment operator) to only be valid for int
to float
specialisations.
Upvotes: 2
Views: 137
Reputation: 1723
EDIT
Maybe this does solve your problem. You only want to fully specialise the constructor for the conversions color<int>
-> color<float>
and vice-versa. This is allowed.
#include <iostream>
using namespace std;
template<typename T>
class color
{
public:
T r,g,b,a;
color(T r, T g, T b, T a) : r(r), g(g), b(b), a(a) {}
template<typename OtherT>
color(const color<OtherT>&);
};
template<>
template<>
color<int>::color(const color<float>& other) :
r(other.r * 255),
g(other.g * 255),
b(other.b * 255),
a(other.a * 255)
{}
int main() {
color<float> c1 = { 1.0f, 1.0f, 1.0f, 1.0f };
color<int> c2 = c1;
cout << c2.r << " " << c2.g << " " << c2.b << " " << c2.a << endl;
return 0;
}
My old answer I think I would prefer though, since this will give hard-to-interpret error if the user puts in a template parameter other than int or float. The other method is very explicit.
Old answer
The main problem with what you want is that you cannot partially specialise a single method in a class template.
If the only two parameters used for template class color are int and float, I would arrange it like this: Have a base template class that contains the common code, and two classes that derive from it and provide the specialised constructors.
template<typename T> class base_color { ... common code between int and float };
Then two classes that have specific conversion constructors
class int_color : public base_color<int>
{
public:
int_color(const float_color&) { ... }
}
class float_color : public base_color<float>
{
public:
float_color(const int_color&) { ... }
}
Upvotes: 2