keyboardwarrior
keyboardwarrior

Reputation: 47

Class template inside a class template

I am using Xcode and I have provided two headers below: Spheres.h and Vector3.h which both are suppose to be templates. Vector3.h compiles without any errors.

Spheres.h do not compile and returns this warning: "Expected ')'" and points to:

Sphere(const Vector3<T>& c,const float r);
                     ^

This error occurs at any place inside Sphere.h where I have a Vector<T>. If I remove <T> the code can compile, I do not understand. Why? I want to be able to initialise Vector3<T> with same template<typename T> as Sphere<T>.

Please help!

Sphere.h

#ifndef SPHERE
#define SPHERE

#include "Vector3.h"

template <typename T>
class Sphere
{
public:
    // Constructors

    // Default
    Sphere();

    // Copy
    Sphere(const Sphere<T>& sphere);

    Sphere(const Vector3<T>& c, const float r);

    // Destructor
    ~Sphere();

    // Get properties

    const Vector3<T>& GetCenter() const;
    const float& GetRadius() const;

    // Set Properties

    void SetCenter(const Vector3<T>& vector);
    void SetRadius(const float& r);

    // Methods

    // Calculate sphere area: A = 4 * PI * r^2
    const float GetArea() const;

    // Calculate sphere volume: V =  (4 * PI * r^3) / 3
    const float GetVolume() const;

    // Return if given point of vector3 is within sphere
    const bool PointIntersect(const Vector3<T>& point) const;

    bool Overlap(const Sphere<T>& sphere);

    // Tries to load data from a string
    bool Load(std::string string) const;

    // Operators

    // Assignment operator
    Sphere<T>& operator=(const Sphere<T>& sphere);

    // Less than operator <
    bool operator<(const Sphere<T>& s) const;

    // Greater than operator >
    bool operator>(const Sphere<T>& s) const;

    // Less or equal operator <=
    bool operator<=(const Sphere<T>& s) const;

    // Greater or equal operator >=
    bool operator>=(const Sphere<T>& s) const;

     // Equal operator ==
    bool operator ==(const Sphere<T>& s) const;

    // Not equal operator !=
    bool operator!=(const Sphere<T>& s) const;

    // Print a sphere to console with cout
    friend std::ostream& operator<<(std::ostream& out, const Sphere<T>& s);

private:
    T radius;
    Vector3<T> center;
};

// Implementation

// Constructor
// Default
template<typename T>
Sphere<T>::Sphere()
{
    // Created empty sphere
}

// Copy
template<typename T>
Sphere<T>::Sphere(const Sphere<T>& sphere)
{
    this->SetPosition(sphere.GetPosition());
    this->SetRadius(sphere.GetRadius());
    this->SetCenter(sphere.GetCenter());
}

template<typename T>
Sphere<T>::Sphere(const Vector3<T>& center,const float radius)
{
    this->SetPosition(center);
    this->radius = radius;
}


// Destructor
template<typename T>
Sphere<T>::~Sphere()
{
    // Nothing to delete.
}

// Properties

// Get

template<typename T>
const Vector3<T>& Sphere<T>::GetCenter() const
{

    return center;
}

template<typename T>
const float& Sphere<T>::GetRadius() const
{
    return radius;
}

// Set

template<typename T>
void Sphere<T>::SetCenter(const Vector3<T>& vector)
{
    this->SetPosition(vector);
}

template<typename T>
void Sphere<T>::SetRadius(const float& r)
{
    radius = r;
}

// Methods


// Calculate sphere area: A = 4 * PI * r^2
template<typename T>
const float Sphere<T>::GetArea() const
{
    float temp = 4 * pi * powf(this->GetRadius(), 2);
    return temp;
}

// Calcutate sphere volume: V =  (4 * PI * r^3) / 3
template<typename T>
const float Sphere<T>::GetVolume() const
{
    float temp = (4 * pi * powf(radius, 3))/3;
    return temp;
}

// Return if given point of vector3 is within sphere
template<typename T>
const bool Sphere<T>::PointIntersect(const Vector3<T>& point) const
{
    if (point.GetDistance(this->GetCenter(), point) >= this->radius)
    {
        return true;
    }
    return false;
}

template<typename T>
bool Sphere<T>::Overlap(const Sphere<T>& sphere)
{
    // Calculate the distance between the two spheres
    float distance = Vector3::GetDistance(sphere.GetCenter(), this->GetCenter());

    // Calculate the length of both radiances
    float radiusSum = sphere.radius + this->radius;

    // if the length of radiance is greater than the distace -> there is a overlap
    if (radiusSum > distance)
        return true;
    return false;
}

// Tries to load data from a string
template<typename T>
bool Sphere<T>::Load(std::string string) const
{
    return false;
}

// Operators

// Asignment operator
template<typename T>
Sphere& Sphere<T>::operator=(const Sphere<T>& sphere)
{
    this->SetCenter(sphere.GetCenter());
    this->radius = sphere.radius;
    return *this;
}

// Less than operator <
template<typename T>
bool Sphere<T>::operator<(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 < v2)
        return true;
    return false;
}

// Greater than operator >
template<typename T>
bool Sphere<T>::operator>(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 > v2)
        return true;
    return false;
}

// Less or equal operator <=
template<typename T>
bool Sphere<T>::operator<=(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 < v2)
        return true;
    if (v1 == v2)
        return true;
    return false;
}

// Greater or equal operator >=
template<typename T>
bool Sphere<T>::operator >=(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 > v2)
        return true;
    if (v1 == v2)
        return true;
    return false;
}

// Equal operator ==
template<typename T>
bool Sphere<T>::operator ==(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 == v2)
        return true;
    return false;
}

// Not equal operator !=
template<typename T>
bool Sphere<T>::operator !=(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 != v2)
        return true;
    return false;
}

// Print a sphere to console with cout
template<typename T>
std::ostream& operator<<(std::ostream& out, const Sphere<T>& s)
{
    std::cout << "c:(" << s.GetCenter() << ") r:" << s.GetRadius();
    return out;
}

#endif

Vector3.h

#ifndef VECTOR3
#define VECTOR3

// IO standard library
#include <iostream>

template<typename Type>
class Vector3
{
public:
    // Constructor
    Vector3(const Type& x, const Type& y, const Type& z);

    // Copy constructor
    Vector3(const Vector3<Type>& v);

    // Destructor
    ~Vector3();

    // Get properties
    const Type& GetX() const;
    const Type& GetY() const;
    const Type& GetZ() const;

    // Set properties
    void SetX(const Type& value);
    void SetY(const Type& value);
    void SetZ(const Type& value);

    // Methods

    // Return length of the vector3<Type>
    const float GetLength() const;

    // Return the distance between two vector3<type>
    const float GetDistance(const Vector3<Type>& v1, const Vector3<Type>& v2) const;

    // Operators

    // Assignment =
    Vector3<Type>& operator=(const Vector3<Type>& v);

    // Addition
    Vector3<Type> operator+(const Vector3<Type>& v);

    // Subtraction
    Vector3<Type> operator-(const Vector3<Type>& v);

    // Scalar product
    float operator*(const Vector3<Type>& v);

    // Multiplication
    Vector3<Type> operator*(const float& s);

    // Friend multiplication
    friend Vector3<Type> operator*(const float& s, const Vector3<Type>& v);

    // Cout: printing a vector3 to console
    friend std::ostream& operator<<(std::ostream& out, const Vector3<Type>& v);

private:
    Type x;
    Type y;
    Type z;
};

// Template implementation

// Constructor
template<typename Type>
Vector3<Type>::Vector3(const Type& x, const Type& y, const Type& z)
{
    this->SetX(x);
    this->SetY(y);
    this->SetZ(z);
}

// Copy constructor
template<typename Type>
Vector3<Type>::Vector3(const Vector3<Type>& v)
{
    this->SetX(x);
    this->SetY(y);
    this->SetZ(z);
}

// Destructor
template<typename Type>
Vector3<Type>::~Vector3<Type>()
{
    // Nothin to delete
}

// Get Properties
template<typename Type>
const Type& Vector3<Type>::GetX() const
{
    return this->x;
}

template<typename Type>
const Type& Vector3<Type>::GetY() const
{
    return this->y;
}

template<typename Type>
const Type& Vector3<Type>::GetZ() const
{
    return this->z;
}

// Set properties
template<typename Type>
void Vector3<Type>::SetX(const Type& value)
{
    this->x = value;
}

template<typename Type>
void Vector3<Type>::SetY(const Type& value)
{
    this->x = value;
}

template<typename Type>
void Vector3<Type>::SetZ(const Type& value)
{
    this->x = value;
}

// Methods

// Return length of the vector3<Type>
template<typename Type>
const float Vector3<Type>::GetLength() const
{
    float length = 0;

    length = sqrtf(powf(x,2) + powf(y,2) + powf(z,2));
    return length;
}

// Return the distance between two vector3's
template<typename Type>
const float Vector3<Type>::GetDistance(const Vector3<Type>& v1, const Vector3<Type>& v2) const
{
return sqrtf(powf((v2.x - v1.x), 2) +
             powf((v2.y - v1.y), 2) +
             powf((v2.z - v1.z), 2) );
}

// Operators

// Assignment
template<typename Type>
Vector3<Type>& Vector3<Type>::operator=(const Vector3<Type>& v)
{
    this->SetX(v.x);
    this->SetY(v.y);
    this->SetZ(v.z);
    return *this;
}

// Addition
template<typename Type>
Vector3<Type> Vector3<Type>::operator+(const Vector3<Type>& v)
{
    Type x, y, z;

    x = this->x + v.x;
    y = this->y + v.y;
    z = this->z + v.z;

    Vector3<Type> temp(x, y, z);
    return temp;
}

// Subtraction
template<typename Type>
Vector3<Type> Vector3<Type>::operator-(const Vector3<Type>& v)
{
    Type x,y,z;

    x = this->x - v.x;
    y = this->y - v.y;
    z = this->z - v.z;

    Vector3<Type> temp(x, y, z);
    return temp;
}

// Scalar product
template<typename Type>
float Vector3<Type>::operator*(const Vector3<Type>& v)
{
    float scalarP = (this->GetX() * v.x) + (this->GetY() * v.y) + (this->GetZ() * v.z);

    return scalarP;
}

template<typename Type>
Vector3<Type> Vector3<Type>::operator*(const float& s)
{
    Vector3 temp(this->GetX() * s, this->GetY() * s, this->GetZ() * s);
     return temp;
}

template<typename Type>
Vector3<Type> operator*(const float& s, const Vector3<Type>& v)
{
    Vector3<Type> temp(v.x * s, v.y * s, v.z * s);
    return temp;
}


// Cout: printing a vector3 to console
template<typename Type>
std::ostream& operator<<(std::ostream& out, const Vector3<Type>& v)
{
    std::cout << "x:" << v.x
              << " y:" << v.y
              << " z:" << v.z;
    return out;
}

#endif

Upvotes: 2

Views: 159

Answers (2)

Mark H
Mark H

Reputation: 13897

The following compiles fine on gcc. Other than fixing the obvious syntax errors, I've also modified the constructors to fully initialize the object. Other possible solutions are to give Vector3 a default constructor (such that it can have a default initial value), or make center a Vector3<T>*.

#ifndef SPHERE
#define SPHERE

#include "vector3.h"

template <typename T>
class Sphere
{
public:
    // Constructors

    // Default
    Sphere();

    // Copy
    Sphere(const Sphere<T>& sphere);

    Sphere(const Vector3<T>& c, const float r);

    // Destructor
    ~Sphere();

    // Get properties

    const Vector3<T>& GetCenter() const;
    const float& GetRadius() const;

    // Set Properties

    void SetCenter(const Vector3<T>& vector);
    void SetRadius(const float& r);

    // Methods

    // Calculate sphere area: A = 4 * PI * r^2
    const float GetArea() const;

    // Calculate sphere volume: V =  (4 * PI * r^3) / 3
    const float GetVolume() const;

    // Return if given point of vector3 is within sphere
    const bool PointIntersect(const Vector3<T>& point) const;

    bool Overlap(const Sphere<T>& sphere);

    // Tries to load data from a string
    bool Load(std::string string) const;

    // Operators

    // Assignment operator
    Sphere<T>& operator=(const Sphere<T>& sphere);

    // Less than operator <
    bool operator<(const Sphere<T>& s) const;

    // Greater than operator >
    bool operator>(const Sphere<T>& s) const;

    // Less or equal operator <=
    bool operator<=(const Sphere<T>& s) const;

    // Greater or equal operator >=
    bool operator>=(const Sphere<T>& s) const;

     // Equal operator ==
    bool operator ==(const Sphere<T>& s) const;

    // Not equal operator !=
    bool operator!=(const Sphere<T>& s) const;

    // Print a sphere to console with cout
    friend std::ostream& operator<<(std::ostream& out, const Sphere<T>& s);

private:
    T radius;
    Vector3<T> center;
};

// Implementation

// Constructor
// Default
template<typename T>
Sphere<T>::Sphere()
    : radius(0), center(Vector3<T>(0,0,0))
{
    // Created empty sphere
}

// Copy
template<typename T>
Sphere<T>::Sphere(const Sphere<T>& sphere)
    : radius(sphere.radius), center(sphere.center)
{
}

template<typename T>
Sphere<T>::Sphere(const Vector3<T>& center, const float radius)
    : radius(radius), center(center)
{
}


// Destructor
template<typename T>
Sphere<T>::~Sphere()
{
    // Nothing to delete.
}

// Properties

// Get

template<typename T>
const Vector3<T>& Sphere<T>::GetCenter() const
{
    return center;
}

template<typename T>
const float& Sphere<T>::GetRadius() const
{
    return radius;
}

// Set

template<typename T>
void Sphere<T>::SetCenter(const Vector3<T>& vector)
{
    this->SetPosition(vector);
}

template<typename T>
void Sphere<T>::SetRadius(const float& r)
{
    radius = r;
}

// Methods

const float pi = 3.14;
// Calculate sphere area: A = 4 * PI * r^2
template<typename T>
const float Sphere<T>::GetArea() const
{
    float temp = 4 * pi * powf(this->GetRadius(), 2);
    return temp;
}

// Calcutate sphere volume: V =  (4 * PI * r^3) / 3
template<typename T>
const float Sphere<T>::GetVolume() const
{
    float temp = (4 * pi * powf(radius, 3))/3;
    return temp;
}

// Return if given point of vector3 is within sphere
template<typename T>
const bool Sphere<T>::PointIntersect(const Vector3<T>& point) const
{
    if (point.GetDistance(this->GetCenter(), point) >= this->radius)
    {
        return true;
    }
    return false;
}

template<typename T>
bool Sphere<T>::Overlap(const Sphere<T>& sphere)
{
    // Calculate the distance between the two spheres
    float distance = Vector3<T>::GetDistance(sphere.GetCenter(), this->GetCenter());

    // Calculate the length of both radiances
    float radiusSum = sphere.radius + this->radius;

    // if the length of radiance is greater than the distace -> there is a overlap
    if (radiusSum > distance)
        return true;
    return false;
}

// Tries to load data from a string
template<typename T>
bool Sphere<T>::Load(std::string string) const
{
    return false;
}

// Operators

// Asignment operator
template<typename T>
Sphere<T>& Sphere<T>::operator=(const Sphere<T>& sphere)
{
    this->SetCenter(sphere.GetCenter());
    this->radius = sphere.radius;
    return *this;
}

// Less than operator <
template<typename T>
bool Sphere<T>::operator<(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 < v2)
        return true;
    return false;
}

// Greater than operator >
template<typename T>
bool Sphere<T>::operator>(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 > v2)
        return true;
    return false;
}

// Less or equal operator <=
template<typename T>
bool Sphere<T>::operator<=(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 < v2)
        return true;
    if (v1 == v2)
        return true;
    return false;
}

// Greater or equal operator >=
template<typename T>
bool Sphere<T>::operator >=(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 > v2)
        return true;
    if (v1 == v2)
        return true;
    return false;
}

// Equal operator ==
template<typename T>
bool Sphere<T>::operator ==(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 == v2)
        return true;
    return false;
}

// Not equal operator !=
template<typename T>
bool Sphere<T>::operator !=(const Sphere<T>& s) const
{
    float v1 = this->GetVolume();
    float v2 = s.GetVolume();

    if (v1 != v2)
        return true;
    return false;
}

// Print a sphere to console with cout
template<typename T>
std::ostream& operator<<(std::ostream& out, const Sphere<T>& s)
{
    std::cout << "c:(" << s.GetCenter() << ") r:" << s.GetRadius();
    return out;
}

#endif

Upvotes: 1

Teivaz
Teivaz

Reputation: 5665

It is because your class Sphere requires Vector3 as template class. Like here:

~Sphere();

// Get properties

const Vector3<T>& GetCenter() const;
const float& GetRadius() const;

// Set Properties

But when you provide Sphere with Vector3<T> it will result in someting like this Vector3<T><T>

Upvotes: 0

Related Questions