开发者

Implicit conversion not happening when I templatize

开发者 https://www.devze.com 2023-01-28 15:58 出处:网络
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-lis

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消