I'm developing static library for matrix operations using templates wherein we can perform basic matrix operations on various datatypes(short, int, long, long long, float, double, long double). But as far as I know when using templates, class declaration and definition can't be kept in separate files(.h and .cpp files). If this is the case how do I create the library without exposing my implementation code(only class syntax declaration and library has to be provided to an other user). This is what I've written so far
MatrixClass.h
#ifndef __MATRIXCLASS_H__
#define __MATRIXCLASS_H__
#include<iostream>
#include<vector>
template<typename T>
class CMatrix { 
public:
    CMatrix();
    ~CMatrix();
    unsigned long rows;
    unsigned long cols;
    std::vector<std::vector<T> > data;
    void setMatrixSize(unsigned long rows, unsigned long cols);
    void printMatrix();
    void add(CMatrix<T>& A, CMatrix<T>& B);
    void sub(CMatrix<T>& A, CMatrix<T>& B);
    void mul(CMatrix<T>& A, CMatrix<T>& B);
};
template<typename T>
CMatrix<T>::CMatrix() {
    this->rows = 0;
    this->cols = 0;
    data.clear();
}
template<typename T>
CMatrix<T>::~CMatrix() {
    this->rows = 0;
    this->cols = 0;
    data.clear();
}
template<typename T>
void CMatrix<T>::setMatrixSize(unsigned long rows, unsigned long cols) {
    this->rows = rows;
    this->cols = cols;
    data.clear();
    data.resize(cols, std::vector<T>(rows, 0));
}
template<typename T>
void CMatrix<T>::printMatrix() {
    for(unsigned long i = 0; i < rows; i++) {
        for(unsigned long j = 0; j < cols; j++) {
            std::cout << data.at(i).at(j) << "\t";
        }
        std::cout << std::endl;
    } 
}
template<typename T>
void CMatrix<T>::add(CMatrix<T>& A, CMatrix<T>& B) {
    if((A.rows == B.rows) && (A.cols == B.cols)) {
        for(unsigned long i = 0; i < rows; i++) {
            for(unsigned long j = 0; j < cols; j++) {
                data.at(i).at(j) = A.data.at(i).at(j) + B.data.at(i).at(j);
            }
        }
    }
}
template<typename T>
void CMatrix<T>::sub(CMatrix<T>& A, CMatrix<T>& B) {
    if((A.rows == B.rows) && (A.cols == B.cols)) {
        for(unsigned long i = 0; i < rows; i++) {
            for(unsigned long j = 0; j < cols; j++) {
                data.at(i).at(j) = A.data.at(i).at(j) - B.data.at(i).at(j);
            }
        }
    }
}
template<typename T>
void CMatrix<T>::mul(CMatrix<T>& A, CMatrix<T>& B) {
    if((A.cols == B.rows) && (rows == A.rows) && (cols == B.cols)) {
        for(unsigned long i = 0; i < A.rows; i++) {
            for(unsigned long j = 0; j < B.cols; j++) {
                for(unsigned long k = 0; k < A.cols; k++) {
                    data.at(i).at(j) += A.data.at(i).at(k) * B.data.at(k).at(j);
                }
            }
        }
    }
}
#endif
