I am currently studying C++ with CLion.
[Problem]
The problem is that the compiler produces linker errors when I tried to implement "matrix_2_2" templated class equipped with various overloaded operators and "triangular" templated function. I have no idea why the linker produces such errors since I did instantiation for every types using extern template phrases in the .h file. I appreciate your help.
"matrix_2_2<double>::operator[](unsigned long)", referenced from:
_main in main.cpp.o
"matrix_2_2<double>::operator*=(matrix_2_2<double> const&)", referenced from:
_main in main.cpp.o
"operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, matrix_2_2<double> const&)", referenced from:
_main in main.cpp.o
"operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, matrix_2_2<int> const&)", referenced from:
_main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
[Information about my class and functions]
"matrix_2_2" (which means 2 x 2 matrix) is a templated class with <typename T>, and has a member variable "element" with type "T *" to store 2 x 2 matrix elements. And I used overloaded operators to implement various matrix and scalar operations.
"triangular" is a templated function which accepts a single int argument, n, and calculate and return n(n+1)/2, of type T.
[Codes]
Below are my C++ codes.
My main.cpp is as follows.
#include "matrix_2_2.h"
#include <iostream>
int main() {
using namespace std;
cout << triangular<matrix_2_2<int>>(10) << endl;
matrix_2_2<double> m1 = 1.1;
m1[1][0] = -0.125;
m1[0][0] += 0.5;
m1 *= triangular<matrix_2_2<double>>(20);
cout << m1 << endl;
return 0;
}
My matrix_2_2.h file is as follows.
#ifndef MATRIX_TEMPLATED_MATRIX_2_2_H
#define MATRIX_TEMPLATED_MATRIX_2_2_H
#include <cstddef>
#include <iostream>
using namespace std;
template <typename T>
class matrix_2_2 {
private:
T *element[2];
public:
// Default constructor
matrix_2_2() {element[0] = nullptr; element[1] = nullptr;};
matrix_2_2(T n) {element[0][0] = n; element[0][1] = 0; element[1][0] = 0; element[1][1] = n;};
// Operator overloading
matrix_2_2 &operator+=(matrix_2_2 const &);
matrix_2_2 operator+(matrix_2_2 const &);
matrix_2_2 &operator*=(matrix_2_2 const &);
matrix_2_2 operator*(matrix_2_2 const &);
matrix_2_2 &operator/=(T const &);
matrix_2_2 operator/(T const &);
T *operator[](size_t);
friend ostream &operator<<(ostream &out, matrix_2_2 const &m);
};
template <typename T> T triangular(int n);
extern template class matrix_2_2<double>;
extern template class matrix_2_2<int>;
extern template class matrix_2_2<short>;
extern template class matrix_2_2<float>;
extern template class matrix_2_2<long>;
extern template int triangular<int>(int);
extern template double triangular<double>(int);
extern template short triangular<short>(int);
extern template float triangular<float>(int);
extern template long triangular<long>(int);
extern template matrix_2_2<int> triangular<matrix_2_2<int>>(int);
extern template matrix_2_2<double> triangular<matrix_2_2<double>>(int);
#endif //MATRIX_TEMPLATED_MATRIX_2_2_H
My overloaded "[]" and "<<" operators, "triangular" functions and some instantiation phrases are as follows.(Which are in the "matrix_2_2.cpp" file.
template class matrix_2_2<double>;
template class matrix_2_2<int>;
template class matrix_2_2<short>;
template class matrix_2_2<float>;
template class matrix_2_2<long>;
template int triangular<int>(int);
template double triangular<double>(int);
template short triangular<short>(int);
template float triangular<float>(int);
template long triangular<long>(int);
template matrix_2_2<int> triangular<matrix_2_2<int>>(int);
template matrix_2_2<double> triangular<matrix_2_2<double>>(int);
template <typename T>
T *matrix_2_2<T>::operator[](size_t n) {
return element[n];
}
template <typename T>
ostream &operator<<(ostream &out, matrix_2_2<T> const &m) {
out << "[" << '\t' << m.element[0][0] << '\t' << m.element[0][1] << "]\n";
out << "[" << '\t' << m.element[1][0] << '\t' << m.element[1][1] << "]\n";
return out;
}
template <typename T>
T triangular(int n) {
T result = n * (n - 1) / 2;
return result;
}