0

I am having an issue trying to overload the addition operator on a template class for complex numbers.

In my .h I have forward declaration for both the class and the operator function function, and I specifically overloaded operator+<T> rather than just operator+ so that it works for multiple types. It compiles fine when I only include the .h file, but as soon as I try to declare MyComplex<int> it gives some weird errors that I'm having difficulty deciphering.

my_complex.h:

#ifndef _MY_COMPLEX_H
#define _MY_COMPLEX_H

using namespace std;

//forward declarations
template<typename T> class MyComplex;

template<typename T> MyComplex<T> operator+(const MyComplex<T>& cmplx1, const MyComplex<T>& cmplx2);

template<typename T>
class MyComplex{
        private:
                T _real;
                T _imaginary;
        public:
                MyComplex();
                MyComplex(T real, T img);
                T getReal();
                T getImaginary();
                void setReal(T real);
                void setImaginary(T img);

                friend MyComplex operator+<T>(const MyComplex& cmplx1, const MyComplex& cmplx2);
}
#endif

my_complex.cpp:

#include "my_complex.h"
...
template <typename T>
MyComplex<T> operator+(const MyComplex<T>& cmplx1, const MyComplex<T>& cmplx2){
        MyComplex<T> temp;
        temp._real = cmplx1._real + cmplx2._real;
        temp._imaginary = cmplx1._imaginary + cmplx2._imaginary;

        return temp;
}
...

main.cpp:

#include "my_complex.h"

int main(int argc, char* argv[]){
        MyComplex<int> cmplx1 = MyComplex<int>(3, 5);//error is here
        MyComplex<int> cmplx2 = MyComplex<int>(5, 7);

        cmplx1 = cmplx1 + cmplx2;

        return 0;

}

It compiles fine when I only include the .h file in main file, but as soon as I try to declare MyComplex<int> it gives some errors that I am having difficulty deciphering.

In file included from /usr/include/c++/7/bits/stl_algobase.h:67:0,
                     from /usr/include/c++/7/bits/char_traits.h:39,
                     from /usr/include/c++/7/ios:40,
                     from /usr/include/c++/7/ostream:38,
                     from /usr/include/c++/7/iostream:39,
                     from main.cpp:1:
    /usr/include/c++/7/bits/stl_iterator.h: In instantiation of ‘class std::reverse_iterator<int>’:
    /usr/include/c++/7/bits/stl_iterator.h:400:5:   required by substitution of ‘template<class _Iterator> std::reverse_iterator<_Iterator> std::operator+(typename std::reverse_iterator<_Iterator>::difference_type, const std::reverse_iterator<_Iterator>&) [with _Iterator = int]’
    my_complex.h:36:20:   required from ‘class MyComplex<int>’
    main.cpp:8:17:   required from here
    /usr/include/c++/7/bits/stl_iterator.h:101:11: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<int>’
         class reverse_iterator
               ^~~~~~~~~~~~~~~~
    /usr/include/c++/7/bits/stl_iterator.h:115:55: error: no type named ‘difference_type’ in ‘struct std::iterator_traits<int>’
           typedef typename __traits_type::difference_type difference_type;
                                                           ^~~~~~~~~~~~~~~
    /usr/include/c++/7/bits/stl_iterator.h:116:48: error: no type named ‘pointer’ in ‘struct std::iterator_traits<int>’
           typedef typename __traits_type::pointer  pointer;
                                                    ^~~~~~~
    /usr/include/c++/7/bits/stl_iterator.h:117:50: error: no type named ‘reference’ in ‘struct std::iterator_traits<int>’
           typedef typename __traits_type::reference  reference;
                                                      ^~~~~~~~~
    /usr/include/c++/7/bits/stl_iterator.h: In instantiation of ‘class std::move_iterator<int>’:
    /usr/include/c++/7/bits/stl_iterator.h:1201:5:   required by substitution of ‘template<class _Iterator> std::move_iterator<_IteratorL> std::operator+(typename std::move_iterator<_IteratorL>::difference_type, const std::move_iterator<_IteratorL>&) [with _Iterator = int]’
    my_complex.h:36:20:   required from ‘class MyComplex<int>’
    main.cpp:8:17:   required from here
    /usr/include/c++/7/bits/stl_iterator.h:1019:50: error: no type named ‘reference’ in ‘struct std::iterator_traits<int>’
           typedef typename __traits_type::reference  __base_ref;
                                                      ^~~~~~~~~~
    /usr/include/c++/7/bits/stl_iterator.h:1023:57: error: no type named ‘iterator_category’ in ‘struct std::iterator_traits<int>’
           typedef typename __traits_type::iterator_category iterator_category;
                                                             ^~~~~~~~~~~~~~~~~
    /usr/include/c++/7/bits/stl_iterator.h:1024:52: error: no type named ‘value_type’ in ‘struct std::iterator_traits<int>’
           typedef typename __traits_type::value_type   value_type;
                                                        ^~~~~~~~~~
    /usr/include/c++/7/bits/stl_iterator.h:1025:55: error: no type named ‘difference_type’ in ‘struct std::iterator_traits<int>’
           typedef typename __traits_type::difference_type difference_type;
                                                           ^~~~~~~~~~~~~~~
    /usr/include/c++/7/bits/stl_iterator.h:1032:24: error: no type named ‘reference’ in ‘struct std::iterator_traits<int>’
         __base_ref>::type  reference;
                            ^~~~~~~~~
  • This doesn’t address the question, but names that begin with an underscore followed by a capital letter (`_MY_COMPLEX_H`) and names that contain two consecutive underscores are reserved for use by the implementation. Don’t use them in your code. – Pete Becker Nov 09 '19 at 23:52

1 Answers1

0

You cannot define a templated method in a .cpp file, put it in the header and it should work. See https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl

Furthermore, this

friend MyComplex operator+<T>(const MyComplex& cmplx1, const MyComplex& cmplx2);
// should match the forward declaration
friend MyComplex<T> operator+<>(const MyComplex<T>& cmplx1, const MyComplex<T>& cmplx2);

so you should add <T>

This actually does not explain your error, but the error message does not fit the files you gave, the .hpp has not 36 lines but that's where the error is, so debugging this is quite hard.

n314159
  • 4,990
  • 1
  • 5
  • 20
  • Sorry, the error occurs on the line 24 of the .h file where the friend function is declared. I didn't copy everything perfectly. – Owen Hunter Nov 09 '19 at 23:15
  • I edited my answer. You had the at the wrong position. Please change all of that and compile again. The error you have is indeed very confusing, maybe you get rid of it this way. – n314159 Nov 09 '19 at 23:25
  • Also I put template specific declaration over my methods in the .cpp file which I thought would allow me to define a templated method in a .cpp file. Is that not correct? – Owen Hunter Nov 09 '19 at 23:26
  • That is correct, see also my link. Then the only errors I see are the declarations I told you above. – n314159 Nov 09 '19 at 23:28
  • Ah, you also need a <> after the friend declaration, see https://stackoverflow.com/questions/39678663/forward-declaration-of-template-friend-function – n314159 Nov 09 '19 at 23:32
  • Thank you so much!! That fixed it. Just a couple little errors to wrap up but they're a lot more descriptive so I can figure it out. – Owen Hunter Nov 09 '19 at 23:38