The error I get is
(base) ethanordaz@Ethans-MBP Fraction % g++ main.cpp fractionClass.cpp
Undefined symbols for architecture x86_64:
"fraction::Fraction fraction::Fraction::operator*<fraction::Fraction>(fraction::Fraction)", referenced from:
_main in main-8169dc.o
"fraction::Fraction fraction::Fraction::operator+<int>(int)", referenced from:
_main in main-8169dc.o
ld: symbol(s) not found for architecture x86_64
Main.cpp
#include <iostream>
#include <cmath>
#include <string>
#include "fractionClass.h"
int main()
{
fraction::Fraction myFrac2(2,3);
fraction::Fraction newFrac = myFrac2 + 1;
myFrac2 = newFrac*myFrac2;
std::cin >> myFrac2;
std::cout << myFrac2 << std::endl;
std::cout << newFrac << std::endl;
return 0;
}
fractionClass.cpp
#include <iostream>
#include <cmath>
#include <string>
#include "fractionClass.h"
namespace fraction {
Fraction::Fraction(int x, int y) {
numerator = x;
denominator = y;
simplify();
}
template <typename Number>
Fraction::Fraction(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
numerator = x * std::pow(10,zeros);
denominator = std::pow(10,zeros);
simplify();
}
Fraction::Fraction(){
}
double Fraction::getDecimal() {
double decimal = (double)numerator/(double)denominator;
return decimal;
}
template <typename Number>
void Fraction::multiply(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
numerator = numerator * x;
denominator = denominator * std::pow(10,zeros);
simplify();
}
void Fraction::multiply(Fraction x) {
numerator = numerator * x.numerator;
denominator = denominator * x.denominator;
simplify();
}
template <typename Number>
void Fraction::divide(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
numerator = numerator * std::pow(10,zeros);
denominator = denominator * x;
simplify();
}
void Fraction::divide(Fraction x) {
numerator = numerator * x.denominator;
denominator = denominator * x.numerator;
simplify();
}
void Fraction::simplify() {
int a = numerator;
int b = denominator;
int greatestCommonDivisor;
int greatestNumber = a>b ? a : b;
while (a%10==0 && b%10==0) {
a = a/10;
b = b/10;
}
while (a%2==0 && b%2==0) {
a = a/2;
b = b/2;
}
do {
while (true) {
if (a%greatestNumber==0 && b%greatestNumber==0) {
greatestCommonDivisor = greatestNumber;
break;
} else {
greatestNumber--;
}
if (greatestNumber <= 0) {
greatestCommonDivisor = 1;
break;
}
}
a = a/greatestCommonDivisor;
b = b/greatestCommonDivisor;
} while (greatestCommonDivisor != 1);
numerator = a;
denominator = b;
}
template <typename Number>
void Fraction::add(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
x = x*denominator;
Number xdenom = std::pow(10,zeros) * denominator;
numerator = numerator * (xdenom/denominator);
denominator = denominator * (xdenom/denominator);
numerator = numerator + x;
simplify();
}
template <typename Number>
void Fraction::sub(Number x) {
int xint = (int)x;
int zeros = 0;
if (xint-x != 0){
std::string tempString = std::to_string(x-xint);
zeros = tempString.size();
}
x = x*denominator;
Number xdenom = std::pow(10,zeros) * denominator;
numerator = numerator * (xdenom/denominator);
denominator = denominator * (xdenom/denominator);
numerator = numerator - x;
simplify();
}
void Fraction::add(Fraction x) {
x.numerator = x.numerator*denominator;
int xdenom = x.denominator * denominator;
numerator = numerator * (xdenom/denominator);
denominator = denominator * (xdenom/denominator);
numerator = numerator + x.numerator;
simplify();
}
void Fraction::sub(Fraction x) {
x.numerator = x.numerator*denominator;
int xdenom = x.denominator * denominator;
numerator = numerator * (xdenom/denominator);
denominator = denominator * (xdenom/denominator);
numerator = numerator - x.numerator;
simplify();
}
std::string Fraction::display() {
simplify();
std::string output = std::to_string(numerator);
output += '/';
output += std::to_string(denominator);
return output;
}
template <typename Number>
Fraction Fraction::operator + (Number pos) {
Fraction toReturn(numerator,denominator);
toReturn.add(pos);
return toReturn;
}
template <typename Number>
Fraction Fraction::operator - (Number pos) {
Fraction toReturn(numerator,denominator);
toReturn.sub(pos);
return toReturn;
}
template <typename Number>
Fraction Fraction::operator / (Number pos) {
Fraction toReturn(numerator,denominator);
toReturn.divide(pos);
return toReturn;
}
template <typename Number>
Fraction Fraction::operator * (Number pos) {
Fraction toReturn(numerator,denominator);
toReturn.multiply(pos);
return toReturn;
}
std::ostream& operator<<(std::ostream& os, const Fraction& frac);
std::istream& operator>>(std::istream& is, Fraction& frac);
std::ostream& operator<<(std::ostream& os, const Fraction& frac) {
os << frac.numerator << "/" << frac.denominator;
return os;
}
std::istream& operator>>(std::istream& is, Fraction& frac) {
is>> frac.numerator >> frac.denominator;
return is;
}
}
fractionClass.h is
#include <iostream>
#include <cmath>
#include <string>
#include <algorithm>
#ifndef FRACTION_H
#define FRACTION_H
namespace fraction {
class Fraction {
private:
int numerator;
int denominator;
public:
Fraction(int x, int y);
template <typename Number>
Fraction(Number x);
Fraction();
double getDecimal();
template <typename Number>
void multiply(Number x);
void multiply(Fraction x);
template <typename Number>
void divide(Number x);
void divide(Fraction x);
void simplify();
template <typename Number>
void add(Number x);
template <typename Number>
void sub(Number x);
void add(Fraction x);
void sub(Fraction x);
std::string display();
template <typename Number>
Fraction operator + (Number pos);
template <typename Number>
Fraction operator - (Number pos);
template <typename Number>
Fraction operator / (Number pos);
template <typename Number>
Fraction operator * (Number pos);
friend std::ostream& operator<<(std::ostream& os, const Fraction& frac);
friend std::istream& operator>>(std::istream& is, Fraction& frac);
};
std::ostream& operator<<(std::ostream& os, const Fraction& frac);
std::istream& operator>>(std::istream& is, Fraction& frac);
}
#endif
It is my first time messing with header files, this code does compile when run in the same space. I am working in macOS but could use windows if it fixes the problem. This code is meant to be a fraction class of sorts, it is still being made but it grew too large, and so I wanted to use multiple files. Can you show me an example of how you would fix this? It would be greatly appreciated. Thank you. The problem was as someone told me templates must be implemented in the header file, and so I have tried, however I can't manage to use them, can Someone show me an example of how you can implement the templates here. Btw I know the templates are the problem, because I removed them and It worked perfectly, however I do not want to write every single function for each data type.