0

I have a header file and an implementation file and (as far as I can tell, I've googled a lot) am implementing it correctly so that it should link.

Header:

#pragma once

//Shapes.h

#include "Camera.h"
#include <cmath>
#include "Defs.h"

template<typename O>
class Sphere{
  O Radius;
  Point3<O> Center;

public:
  Sphere(O radius, Point3<O> center);

  bool quadratic(Ray<O> ray_in, O &result);
  bool intersect(Ray<O> ray_in, rayInfo<O> &info, O t_max, O t_min);
};

cpp:

#include "Shapes.h"

//Shapes.cpp

template<typename O>
Sphere<O>::Sphere(O radius, Point3<O> center) : Radius(radius), Center(center) {}

template<typename O>
bool Sphere<O>::quadratic(Ray<O> ray_in, O &result){
  Point3<O> origin = ray_in.Origin;
  Vec3<O> direction = ray_in.Direction;

  Vec3<O> o = origin-Center;
  O a = direction.dot(direction);
  O b = 2 * direction.dot(o);
  O c = o.dot(o) - (Radius * Radius);
  O discriminant = b * b - 4 * (a * c);

  if (discriminant > 0){
    return (b - sqrt(discriminant) / a);
  }
  else{
    return -1.0;
  }
}

template<typename O>
bool Sphere<O>::intersect(Ray<O> ray_in, rayInfo<O> &info, O t_max, O t_min){

  O result;

  if (quadratic(ray_in, result)){

    if (result > t_max || t_min < result){
      result = -result;
      if (result > t_max || t_min < result){
        return false;
      }
    }

    Point3<O> p = ray_in.at(result);
    Vec3<O> normal =  (p - Center) / Radius;

    info.Point = p;
    info.Normal = normal;
    info.Ray_in = ray_in;
    info.front_face();
    info.Result = result;

    return true;
  }
  else{
    return false;
  }

}

To compile it I'm running:

g++ Source.cpp Shapes.cpp -o a1.o

I really don't know what I'm doing wrong at this point since I'm including Shapes.h wherever it's needed, compiling the implementation, and don't see any syntax errors. My implementation works fine if I don't use the c++ file but move it to the header.

The error I'm getting:

main':
Source.cpp:(.text+0x167): undefined reference toSphere::Sphere(float, Vec3)' /usr/bin/ld: /tmp/ccLUWNoS.o: in function Tracer::iterator(Ray&, float, float&, float&)':
Source.cpp:(.text.ZN6TracerIfE8iteratorER3RayIfEfRfS4[ZN6TracerIfE8iteratorER3RayIfEfRfS4]+0x172): undefined reference toSphere::intersect(Ray, rayInfo&, float, float)' collect2: error: ld returned 1 exit status

  • 1
    The error is complaining about Source.cpp; where is that? – Scott Hunter Dec 31 '20 at 09:13
  • Templates should be defined in header files, otherwise you get link errors. You even said yourself that it works in the header. – john Dec 31 '20 at 09:14
  • As from my knowledge, you cannot have template classes in two files (one in .h and the other in .cpp). Try putting the function definitions in the header file. – D-RAJ Dec 31 '20 at 09:15
  • So in that case I can't have an implementation file if I'm using templates? I thought that might be the issue, but it would be nice to have some workaround for that if it is. – Tippitytopkek Jan 02 '21 at 10:37
  • I'm currently putting everything in the header and it works fine but I wanted to have a separate implementation file for following convention – Tippitytopkek Jan 02 '21 at 10:38

0 Answers0