Implicit conversion not happening when I templatize
Here's a couple of related, but distinct classes. One contains a list of floats; one contains just one. Sometimes I want to, say, multiply these together. In that case, I want to 'promote' the non-list one to a list. Here's the code, which works just the way I want it to.
#define LIST_SZ 4
class Vec1;
class Vec1_list {
public:
Vec1_list() {}
Vec1_list(const Vec1& in);
float x[LIST_SZ];
};
class Vec1 {
public:
Vec1() {}
Vec1(const float& in);
float x;
};
Vec1::Vec1(const float& in) {
x = in;
}
Vec1_list::Vec1_list(const Vec1& in) {
for (int i = 0; i < LIST_SZ; i++) {
x[i] = in.x;
}
}
Vec1_list operator*(const Vec1_list& a, const Vec1_list& b) {
Vec1_list tmp;
for (int i = 0; i < LIST_SZ; i++) {
tmp.x[i] = a.x[i]*b.x[i];
}
return tmp;
}
int main(void) {
Vec1 v1;
Vec1_list v2, v3, answer;
answer = v1*v3;
}
But now say I want to templatize it like so....
#define LIST_SZ 4
template <typename T> class Vec1;
template <typename T>
class Vec1_list {
public:
Vec1_list() {}
Vec1_list(const Vec1<T>& in);
T x[LIST_SZ];
};
template <typename T>
class Vec1 {
public:
Vec1() {}
Vec1(const T& in);
T x;
};
template <typename T>
Vec1<T>::Vec1(const T& in) {
x = in;
}
template <typename T>
Vec1_list<T>::Vec1_list(const Vec1<T>& in) {
for (int i = 0; i < LIST_SZ; i++) {
x[i] = in.x;
}
}
template <typename T>
Vec1_list<T> operator*(const Vec1_list<T>& a, const Vec1_list<T>& b) {
开发者_如何学Go Vec1_list<T> tmp;
for (int i = 0; i < LIST_SZ; i++) {
tmp.x[i] = a.x[i]*b.x[i];
}
return tmp;
}
int main(void) {
Vec1<float> v1;
Vec1_list<float> v2, v3, answer;
answer = v1*v3;
}
The 'mult' causes the compiler to choke this time - it will not automatically invoke my Vec1 -> Vec1_list constructor. Is this a fact of life in C++, or is there some method I can use to get this to happen automatically? The alternative is that I need to have a huge fan out of functions.
You must declare the operator*
as a friend of the Vec1_list
class, so that it will be instantiated when the Vec1_list
is instantiated and then the conversion will be performed.
EDIT: To do so, move the operator* definition to the Vec1_list class template declaration:
friend static Vec1_list operator*(const Vec1_list& a, const Vec1_list& b){
/* ... */
}
Your user-defined conversion through a conversion constructor is not considered by template argument deduction.
The template deduction attempts to find a substitution of the function template parameters that make the parametrized type identical to the arguments types. When it can't, it is allowed (I'm simplifying here) : const / volatile qualification modifications or 'derived to base' pointer conversion.
This is described in section 14.8.2.1/3 of the standard [temp.deduct.call].
I don't know why it doesn't promote to the desired Vec1_list
. But if it's not possible, then one can always do this:
template <typename T>
Vec1_list<T> operator*(const Vec1<T>& a, const Vec1_list<T>& b) {
return Vec1_list<T>(a)*b;;
}
By the way, I'm still digging the original problem.
精彩评论