0

I'm trying to declare a template method on a template class and it's not working for me. It's better to explain by giving the code so here it is: I have this class:

matrix.h

template <class T,int a,int b>
class Matrix {
private:
   int x;
   int y;
public:
   class IllegalOperation();
   template<T,int c,int d>
   Matrix<T,a,b> operator+(const Matrix<T,c,d> m);
   //...
}

matrix.cpp

template<class T,int a,int b>
template<T,int c,int d>
Matrix<T,a,b> Matrix<T,a,b>::operator+(const Matrix<T,c,d> m){
  if(a!=c || b!=d) throw IllegalOperation();
  // add matrices and return the result
}

I'd like this code to work for any 2 types of Matrix and Matrix where a,b,c and d can be different. for example, I want this code to compile and return an error (in run time):

const Matrix<int, 3, 2> m1;
const Matrix<int, 7, 3> m2;
// init m1 and m2
m1+m2;

While this code should compile and run successfully:

const Matrix<int, 3, 2> m1;
const Matrix<int, 3, 2> m2;
// init m1 and m2
m1+m2;

However, when I try to compile the code above I get this error:

no match for âoperator+ in m1+m2

Loay
  • 483
  • 3
  • 18
  • 2
    You want `operator+` to be able to add only matrices _of the same size_, but contradict yourself by using `Matrix` as its argument, where `c` and `d` may not be equal to `a` and `b` respectively. – ForceBru May 28 '17 at 14:42
  • 2
    Besides that error you currently have, you should know about https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – πάντα ῥεῖ May 28 '17 at 14:42
  • @ForceBru I'm not contradicting myself, BUT I want the error to be shown in runtime and not in compile time. I want the code to compile and then give me the error. – Loay May 28 '17 at 14:44
  • "I want the error to be shown in runtime and not in compile time" Don't make the matrix size a template parameter then. – n. m. could be an AI May 28 '17 at 14:46
  • @Loay _" I think in my case it's to separate the implementation."_ Well, that would simply not work :-P – πάντα ῥεῖ May 28 '17 at 14:46
  • @n.m. it's an assignment, I have to do it this way :) – Loay May 28 '17 at 14:47
  • Is this "error to be shown in runtime" a required part of the assignment? Please quote the assignment verbatim in your question, and also provide a [mcve]. – n. m. could be an AI May 28 '17 at 14:48
  • @n.m. "Is this "error to be shown in runtime" a required part of the assignment? " - yes it is, I'm supposed to throw an exception. I don't know why you need this to answer the question but I'll edit the post – Loay May 28 '17 at 14:53
  • This is a rather unusual and senseless requirement that suggests that your instructor doesn't necessarily have a clue. I would rather not assume that without sufficient evidence. This means I want to **read the assignment itself** rather than your interpretation of it, which may or may not be correct. – n. m. could be an AI May 28 '17 at 14:58
  • @n.m. yeah I agree with you but this is what he wants. besides, since it's unusual, it's good to know and learn :D – Loay May 28 '17 at 15:00
  • You want to **quote the requirements verbatim** and also emphasize the unusual part, because everyone who is going to read your question will first assume that you are mistaken. – n. m. could be an AI May 28 '17 at 15:01

1 Answers1

2

Change your code to this (not considering the things that I think might be wrong here, only changed it to make it compile)

#include <type_traits>

template <typename T,int a,int b>
class Matrix {
public:
    template<typename T2, int c, int d>
    Matrix<T,a,b> operator+(const Matrix<T2, c, d>& m) const;
private:
    int x;
    int y;
};

template <typename T,int a,int b>
template <typename T2, int c, int d>
Matrix<T, a, b> Matrix<T, a, b>::operator+(const Matrix<T2, c, d>&) const {
    if(a != c || b != d) {
        throw IllegalOperation{};
    }
    /*constexpr*/ if (!std::is_same<T, T2>::value) {
        throw Error{};
    }
    return *this;
}

int main() {
    const Matrix<int, 3, 2> m1{};
    const Matrix<int, 7, 3> m2{};
    m1 + m2;
    return 0;
}

I've made a few changes here

  1. The operator+ is const, you were trying to call a non const member function on a const object, would not work
  2. The matrix parameter in the addition operator is now taken by reference
  3. The operator+ cannot be defined in the .cpp file as mentioned in the comments, it must go in the header file (if you want to split up the interface and implementation, the best you can do is In the C++ Boost libraries, why is there a ".ipp" extension on some header files)
  4. I usually like having the public section first since it gives the reader a better idea about the interface of the class.
Curious
  • 20,870
  • 8
  • 61
  • 146
  • What would you do when T and T2 are different types? – n. m. could be an AI May 28 '17 at 15:03
  • @n.m. You mean in the `operator+` member? Could you clarify? – Curious May 28 '17 at 15:04
  • Yes, e,g, what happens when you add `Matrix` and `Matrix`? Returning `*this` would compile, but what about an actual addition? – n. m. could be an AI May 28 '17 at 15:07
  • @n.m. ¯\_(ツ)_/¯ OP was having issues with getting code to compile so that's what I fixed. But I can imagine a scenario where that is appropriate, for example if you have `int` and `short`. OP will have to add constraints to that template later on if they want to be more general. – Curious May 28 '17 at 15:09
  • @Curious thank you for answering but as n.m said, the code would compile if T and T2 are different types. I'd like to throw an exception in this case. – Loay May 28 '17 at 15:12
  • @Loay ah, that's what you both meant, I updated the answer to include that. – Curious May 28 '17 at 15:14
  • @Loay keep in mind that usually these sorts of errors are supposed to be caught at compile time in C++. – Curious May 28 '17 at 15:16
  • 2
    @Loay you check that, but you should do that **if and only if this is explicitly spelled out in the assignment**. Otherwise, remove the T2 argument from the inner template altogether. – n. m. could be an AI May 28 '17 at 15:17