-1

I'm getting a redefinition error for every method in the class. I tried to put the .cpp code in the header where the "include Algebra.cpp" is, but didn't change a thing.

// This is the .h file
#ifndef ALGEBRA_H
#define ALGEBRA_H

#include <iostream>

template <size_t rows, size_t cols>
class Matrix {
    double** matrix;
    void debug_print();    
public:
    Matrix();
    Matrix(double (&_matrix)[rows][cols]);
    ~Matrix();

    double calculate_determinant();

};

#include "Algebra.cpp"

#endif
// This is the .cpp file
#include "Algebra.h"

#include <cassert>

template <size_t rows, size_t cols>
Matrix<rows, cols>::Matrix() {...}
// I have defined all the methods below..
Stukata
  • 35
  • 3
  • 1
    "_I tried to put the .cpp code in the header where the "include Algebra.cpp" is, but didn't change a thing._" `#include` does exactly this, so it's obvious, that it didn't change anything. You `#include`ing the .cpp file in the header is exactly the reason for the issue. Don't do that. Additionally: [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) – Algirdas Preidžius May 15 '20 at 11:03
  • Why would you include a .cpp file in a .h file? – CinCout May 15 '20 at 11:03
  • 3
    You know you can end this insanity by just implementing your template in the header file in the first place, right? – WhozCraig May 15 '20 at 11:03
  • 2
    No, it's the other way around. Don't compile `Algebra.cpp`. – Sam Varshavchik May 15 '20 at 11:03
  • Remove `#include "Algebra.cpp"` from `Algebra.h`. – asmmo May 15 '20 at 11:04
  • https://stackoverflow.com/questions/115703/storing-c-template-function-definitions-in-a-cpp-file – sariug May 15 '20 at 11:05
  • https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file , he does the same thing as I do, and also I know that I can remove the cpp including from the header and then include it in the main and compile, but why doesn't it work like I've shown ? – Stukata May 15 '20 at 11:08
  • 2
    The problem is, that many IDEs will compile `.cpp` files. If you want to seperate declaration and implementation in this way, make sure `Algebra.cpp` is _not_ compiled. Thus changing the file name extension is a good idea to make clear it's no translation unit. For example to `.inl`. – Lukas-T May 15 '20 at 11:31
  • remove inclusion of algebra.cpp. IF you are using visual studio: Go to project properties -> Linker settings -> command -> and enter ```/FORCE``` there. It should also remove the error but it is not recommended – Hashir May 15 '20 at 12:00

1 Answers1

0

First, that template function definition belongs in the header file that gets pulled in wherever it's needed with #include "algebra.h".

The reason you're getting problems with this particular setup is that, as several comments have suggested, you're compiling the .cpp file that contains that template function definition. When the compiler compiles "algebra.cpp", it first sees the #include directive at the top of the file, and pulls in the text from "algebra.h". That's fine as far as it goes, but at the end of "algebra.h" it sees #include "algebra.cpp". So it pulls in the text from there.

Now it's compiling "algebra.cpp" inside of "algebra.cpp". The include guard in "algebra.h" works here, so there is no redefinition of the contents of "algebra.h". And then it sees the definition of Matrix<rows, cols>::Matrix(). Still okay, so far.

Now it comes to the end of the code that comes in through the #include directive, so it continues to compile the code in "algebra.cpp", and it again sees the definition of Matrix<rows, cols>::Matrix(), and that's the redefinition that the compiler is complaining about.

That's why you shouldn't do that.

Some folks like to put definitions of member functions of class templates in a separate file from the header that defines the class template. That's okay, but don't compile that file; it should only be compiled as part of the header that uses it. And as a practical matter, that means giving it an extension that makes it clear that it's not a source file to be compiled on its own. When I've used that approach, I use ".inl" as the extension. If you change the name of "algebra.cpp" to "algebra.inl" and make sure that you're not telling the compiler to compile "algebra.inl" this problem should go away.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165