Overloading operator- with template parameter

Hello,

I wrote a STL-like container, which represents a binary tree and which includes iterators. I overloaded the operator '--' in a particular way. Suppose that 'It' is an iterator, then '--It' will move the iterator to the left son, and 'It--' will move the iterator to the right son. And '++It' and 'It++' are equivalent and move the iterator to the father. So far so good, the code compiles and it does what I want.

The problem comes when I want to overload the operator '-'. I would like to be able to write something like:
1
2
NewIt=1-It; // NewIt should point on the left son of It
NewIt=It-1; // NewIt should point on the right son of It. 


So here is the (simplified) code that I wrote:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class ClassA
  {
    int MyData;
    // ...
  };

template <class Type>

class ClassB
  {
    public: class Iterator;

    private:
    
      class Node
        {
          private:

            Type Data;
          
          public:

            friend class ClassB::Iterator;
        };
      
      Node *RootNode;
      
    public:

      class Iterator
        {
          Node *It;

          public:
            Iterator(void){};
            Iterator(Node *R) {It=R;}
        };
  };

template <class Type> const typename ClassB<Type>::Iterator operator-(int n,const typename ClassB<Type>::Iterator &It)
  {
    typename ClassB<Type>::Iterator New=It;
    // ...
    return New;
  }

int main(void)
  {
    ClassB<ClassA>::Iterator It1,It2;
//    It2=1-It1; // Code doesn't compile if this line is uncommented
    return 0;
  }


If I uncomment the line 'It2=1-It1' in the main function, then the code doesn't compile and gives me the following error:

"In function ‘int main()’:
Test.cpp:50:11: error: no match for ‘operator-’ in ‘1 - It1’
Test.cpp:50:11: note: candidate is:
Test.cpp:40:61: note: template<class Type> const typename ClassB::Iterator operator-(int, const typename ClassB<Type>::Iterator&)"

Note that the code will compile and do I want if I write instead
 
It2=operator-<ClassA>(1,It1);

Can anyone tell me what is wrong? Note that, if I don't define ClassB as a template, but write it explicitly with the type ClassA, then the code compiles with no problem. So it seems that the mistake is related to the fact that I use a template parameter.

Thanks for your help!
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
template <class Type> const typename Type operator-(int n,const typename Type &It)
  {
    Type New=It;
    // ...
    return New;
  }

int main(void)
  {
    ClassB<ClassA>::Iterator It1,It2;
    It2=1-It1; 
    return 0;
  }


I really would recommend you use normal functions to do this though. Overloading operators this way is a bit obfuscatory. What should happen when someone writes It2 = -1-It1; /* or */ It2 = 0-It1;?
Last edited on
Thank you for your reply! Well, the int argument is supposed to be positive. May be I should write a test that warns the user if a negative value is entered. I will try your solution as soon as I can get back to my computer (texting from my phone right now).
I tried the solution you proposed, but still the code doesn't compile:
1
2
3
4
5
6
template <class Type> const typename Type operator-(int n,const typename Type &It)
  {
    Type New=It;
    // ...
    return New;
  }

The error message is:
Test.cpp:40:38: error: expected nested-name-specifier before ‘Type’
Test.cpp:40:43: error: expected initializer before ‘operator’

I tried to add the name-specifier 'ClassB<Type>::Iterator' before 'Type', without any success. Any idea?
If you drop the typename it should compile.
However, that's a dangerous function, it could easily report `ambiguous' or worst, don't report. as it pollutes the namespace.
You could use a `tag' for the step type, hardly an improvement.

http://stackoverflow.com/questions/10079941/template-function-with-nested-type-cannot-be-deduced
It would work if you declare that function as a friend, and define it inside the class declaration.

Will check out how does the STL manages random iterators.
Last edited on
I still cannot get the code to compile. But I have the impression that
cire
and
ne555
are mixing my operator- function with another one. I want my function to return an Iterator object, which is a nested class of ClassB which depends on a template parameter Type. The realization of the template parameter in the main function is ClassA. However, if I look at the solution that
cire
proposed,
1
2
3
4
5
6
template <class Type> const typename Type operator-(int n,const typename Type &It)
  {
    Type New=It;
    // ...
    return New;
  }

then it seems to me that it would return an object of type 'Type', that is to say an objet of type ClassA. So I'm not surprised that this does not compile either. Am I missing something?
Type matches to Container<Data>::Iterator (names changed for clarity) so that's what returns.
1
2
3
4
5
6
7
8
//this compiles (which may be bad)
template <class Type> 
const Type operator-(int n,const Type &It)
  {
    Type New=It;
    // ...
    return New;
  }



In my implementation of the STL they are defined outside the container.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
vector{
   typedef __normal_iterator<pointer, vector> iterator;
};

template <class _Iterator, class _Container>
__normal_iterator<
      _Iterator, 
      _Container>
operator+(
   typename __normal_iterator<
         _Iterator, 
         _Container>
   ::difference_type n,
   const __normal_iterator<
         _Iterator, 
         _Container> &it
)
Last edited on
Ok, it seems to work indeed. Thank!
Topic archived. No new replies allowed.