snake_mchaha
snake_mchaha

Reputation: 23

Conversion operator from one templated class to another, related template class

Did search, but couldn't find something that matches my query, it's a bit specific, so here goes.

I have some templated classes (Vector2, Vector3, and Vector4). Trying to define a conversion operator from Vector2 to 3 and 4, and Vector3 to 2 and 4, etc.

template <typename T>
class Vector4 {
    // ...
    operator Vector2<T>() const { return { x, y }; }
    operator Vector3<T>() const { return { x, y, z }; }
    // ...
    T x, y, z, w;
    // ...
}


template <typename T>
class Vector3 {
    // ...
    operator Vector2<T>() const { return { x, y }; }
    operator Vector4<T>() const { return { x, y, z, 0 }; }
    // ...
    T x, y, z;
    // ...
}


template <typename T>
class Vector2 {
    // ...
    operator Vector3<T>() const { return { x, y, 0 }; }
    operator Vector4<T>() const { return { x, y, 0, 0 }; }
    // ...
    T x, y;
    // ...
}

Using Visual Studio 2017 gives me this:

error C2833: 'operator Vector2' is not a recognized operator or type

Any, and all help is appreciated.

Thank you.

Edit: My actual source does have semi-colons after class defs. Forgot to put them in the brief version I posted. Also, yes, there were many errors, but in my experience, it's usually the first one that matters Tried forward declaring:

template <class T> class Vector 3;
template <class T> class Vector 4;

template <typename T> 
class Vector2 {
// ...
}

Edit: Now I get error C2988: unrecognizable template declaration/definition. It's probably worth mentioning that the 3 template classes are in separate files. I originally tried including a header just in one class to get the type conversion operator working, this is what was giving original errors.

Oh, yes. I will definitely be making those explicit. That's always good advice. It was 0430 localtime though... :)

Edit: Nevermind, I'm a spaz. I don't know how I slipped a space in between Vector and the number of dims "Vector 2" != "Vector2". Forward declaration it was. Can't believe I missed something so simple. Kids: Don't code when your so tied, itsa noso good.

Upvotes: 1

Views: 933

Answers (2)

molbdnilo
molbdnilo

Reputation: 66459

You have a circular dependency.
You can resolve it by using converting constructors in one "direction".
This one uses constructors for increasing the dimensions, conversion operators for decreasing them:

template <typename T>
class Vector2 {
    T x, y;
};

template <typename T>
class Vector3 {
    Vector3(const Vector2<T>& v2) : x(v2.x), y(v2.y), z(0) {}
    operator Vector2<T>() const { return { x, y }; }
    T x, y, z;
};

template <typename T>
class Vector4 {
    Vector4(const Vector2<T>& v2) : x(v2.x), y(v2.y), z(0), w(0) {}
    Vector4(const Vector3<T>& v3) : x(v3.x), y(v3.y), z(v3.z), w(0) {}
    operator Vector2<T>() const { return { x, y }; }
    operator Vector3<T>() const { return { x, y, z }; }
    T x, y, z, w;
};

(Insert stern warning about the perils of implicit conversions here.)

Upvotes: 0

Fran&#231;ois Andrieux
Fran&#231;ois Andrieux

Reputation: 29072

When you declare Vector4<T>::operator Vector2<T>() const; you are using the class Vector2<T> before it's been declared. The same thing happens for Vector4<T>::operator Vector3<T>() const;. Forward declare your classes first.

// Forward declarations
template<class T> class Vector2;
template<class T> class Vector3;

template <typename T>
class Vector4 {
    // ...
    operator Vector2<T>() const { return{ x, y }; }
    operator Vector3<T>() const { return{ x, y, z }; }
    // ...
    T x, y, z, w;
    // ...
};


template <typename T>
class Vector3 {
    // ...
    operator Vector2<T>() const { return{ x, y }; }
    operator Vector4<T>() const { return{ x, y, z, 0 }; }
    // ...
    T x, y, z;
    // ...
};


template <typename T>
class Vector2 {
    // ...
    operator Vector3<T>() const { return{ x, y, 0 }; }
    operator Vector4<T>() const { return{ x, y, 0, 0 }; }
    // ...
    T x, y;
    // ...
};

Upvotes: 1

Related Questions