1

So i am learning how to use templates for the first time. I am trying to create simplified vector and point classes. Unfortunately i need to model that a point can be translated by a vector and a vector can be created due to the subtraction of two points.

The problem i am having is i need to include the files in each other. When I include my vector class in my point template header i get a compiler error because the Point class is no longer recognized as a template.

Vector Class (in Vector3D.h)

#include "Point3D.h"

template <class T>
class Vector3D
{
public:
    //Members
    T x,y,z;

    ... //more boring functions

    Point3D<T> operator+ (const Point3D<T>& pt)
    {
        Point3D <T> pt2(x + pt.x, y + pt.y, z + pt.z);
        return pt2;
    }
};

Point Class (in Point3D.h)

#include "Vector3D.h"

template <class K>
class Point3D
{
public:
    //Members
    K x,y,z;

    ...//boring functions of little importance

    // shifts point by a vector
    Point3D<K> operator+ (const Vector3D<K>& other)
    {
        return Point3D<K>(x + other.x, y + other.y, z + other.z);
    }

    //creates a vector from the differnce between two points
    Vector3D<K> operator- (const Point3D<K>& rhs)
    {
        return Vector3D<K>(x-lhs.x,y-lhs.y,z-lhs.z)
    }
};

Now I get the following compiler errors (Intel C++ 15):

1>F:\Dev Repos\Vascular Modeling\Radiation Modeling Projects\CGAL BOOST  INTEL project1\Vector3D.h(197): error : Point3D is not a template
1>      Point3D<T> operator+ (const Point3D<T>& pt)
1>      ^
1>  
1>F:\Dev Repos\Vascular Modeling\Radiation Modeling Projects\CGAL BOOST INTEL project1\Vector3D.h(197): error : Point3D is not a template
1>      Point3D<T> operator+ (const Point3D<T>& pt)

What am i doing wrong? I assume I am attempting to break the laws of physics and creating some kind of loop. Is the solution to make a split file implementation?

Thanks,

Will

crazywill32
  • 390
  • 1
  • 4
  • 12

1 Answers1

0

As mentioned in the comments, you want to use forward declarations. In the case of your template classes, those would look like these:

template <class K> class Point3D; //before defining Vector3D

template <class T> class Vector3D; //before defining Point3D

Assuming that you're also using include guards correctly (if you don't use include guards in this case, the headers will include each other indefinitely and you'll get even weirder error messages), this should make everything compile correctly. Unlike with non-template classes, you don't have to move the implementation of your methods into other files because they are generated when the template is instantiated rather than when they are defined.

As a sidenote, though, it is often recommended to define binary operations as free-standing functions rather than as class members since the rules for implicit conversions are different and slightly more intuitive. Therefore, I would recommend doing something like this instead:

//shifting points by vectors
template <class T>
Point3D<T> operator+ (const Vector3D<T>& vec, const Point3D<T>& pt)
{
    return {vec.x + pt.x, vec.y + pt.y, vec.z + pt.z};
}
template <class T>
Point3D<T> operator+ (const Point3D<T>& pt, const Vector3D<T>& vec)
{
    return vec + pt;
}

//getting a vector from the difference of points
template <class T>
Vector3D<T> operator- (const Point3D<T>& a, const Point3D<T>& b)
{
    return {a.x - b.x, a.y - b.y, a.z - b.z};
}

This also makes the const correctness of these functions slightly more obvious. If you really want to go the extra mile (and you're using C++11, which I assume you are at this point), you can also mark each of these functions as constexpr to make it possible to use your vector/point operations in constant expressions.

hdastwb
  • 149
  • 2