0

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
Harry
  • 2,177
  • 1
  • 19
  • 33
  • 2
    You will have to explicitly instanciate your type. The user will not be able to use your library for any other type that the ones you have explicitly instancitate. – Gojita Sep 09 '19 at 12:51
  • Unrelated: `__MATRIXCLASS_H__` is a reserved identifier (because it starts with two underscores). Underscore + capital letter is also reserved. Do not use names like these. – Max Langhof Sep 09 '19 at 12:53
  • Unrelated to your problem, but please note that all symbols beginning with double underscore (like for example `__MATRIXCLASS_H__`) are reserved in all scopes, you should never define such symbols yourself. See e.g. [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) for more details. – Some programmer dude Sep 09 '19 at 12:54
  • First, please be clear to us about the part of your code that you want to give away (the public API) and the part that you want to keep secret (maybe your _for_ loops in `add`, `sub`, and `mul`?) Templates are powerful because they will use new types. Meaning if there's a special multiply operator for my type T that is invoked deep within `mul` - your template *will* use it - and optimize it. If you hide that - you won't be able to take advantage of that power. – Wyck Sep 09 '19 at 12:54
  • One way to fix the `__MATRIXCLASS_H__` reserved identifier problem is using `MATRIXCLASS_H` instead. – drescherjm Sep 09 '19 at 12:55
  • @Wyck I just want to give only the function syntax not how to they are implemented just like typical C++ header file – Harry Sep 09 '19 at 12:57
  • @Gojita Could you please provide a sample code for that – Harry Sep 09 '19 at 12:59
  • Would you consider _uncluttering_ the implementations from the headers rather than _not exposing_ them? i.e. matrixclass.h includes matrixclass_priv.h that contains the implementations. [See Mistake #9 of Top 25 C++ API design mistakes and how to avoid them.](https://www.acodersjourney.com/top-25-cplusplus-api-design-mistakes-and-how-to-avoid-them/) (You'll have to scroll down to Mistake #9.) – Wyck Sep 09 '19 at 13:04
  • 1
    You will run into this problem if you attempt this: [https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – drescherjm Sep 09 '19 at 13:05
  • what you have is just a template that will only be instantiated in the users code. If you want to hide the template, you need a layer in between – 463035818_is_not_an_ai Sep 09 '19 at 13:05
  • @Wyck It seems Okay to me. But would like to know any bad consequences of using this technique – Harry Sep 09 '19 at 13:12
  • Your question got closed because you asked a more general question without demonstrating an awareness of the details of why templates can only be implemented in headers. If you have a question about consequences of using a specific technique - then you should probably ask a new question that is specifically about that technique - to avoid getting closed as a duplicate again. – Wyck Sep 09 '19 at 13:17
  • @Wyck Can you provide sample code using this technique – Harry Sep 09 '19 at 13:24
  • 1
    @Harry. No, because the question is closed. But read the [Mistake #9](https://www.acodersjourney.com/top-25-cplusplus-api-design-mistakes-and-how-to-avoid-them/) article I linked above. There's an example. – Wyck Sep 09 '19 at 13:25

0 Answers0