0

I am trying to write a container class with iterator. This is my class:

template <class T>
class C{
 private:
  T* v;
  int MAX_SIZE;
  int i;
 public:
  C (int size){
   MAX_SIZE = size;
   v = new T (MAX_SIZE);
   i = 0;
  }

 ~C(){ delete v; }

  class iterator{
   private:
    T* v;
   public:
    iterator(T* ip){ v = ip; }

    void operator++ (){ ++v; }
    void operator-- (){ --v; }
    T    operator*  () { return *v; }
    bool operator!= (const iterator & it) { return v != it.v; }
 };

 iterator begin(){ return iterator (v); }
 iterator end()  { return iterator (&v[MAX_SIZE]); }

 void push_back (T e){
   if (i == MAX_SIZE) throw MaxSizeReached();
   v[i] = e;  
   ++i;
 }

 class MaxSizeReached{};
};

template <class T>
void print(typename C<T>::iterator & start, typename C<T>::iterator & end){
 for (typename C<T>::iterator s (start), e (end); s != e; ++s){
   std::cout << *s << '\n';
 }
}

int main(){
 C<int> ic (3);
 C<float> fc (4);
 C<char> cc (3);

 ic.push_back (56);
 ic.push_back (76);
 ic.push_back (88);

 print<int>(ic.begin(), ic.end());

 return 0;
}

g++ 4.5 throws this error:

templatizedCustomIterator.c++: In function ‘int main()’:
templatizedCustomIterator.c++:71:35: error: no matching function for call to ‘print(C<int>::iterator, C<int>::iterator)

Which is incorrect - definition of print() or the call?

badmaash
  • 4,775
  • 7
  • 46
  • 61

2 Answers2

3

Have a look the function template:

template<T>
void print(typename C<T>::iterator & start, typename C<T>::iterator & end);

And your usage:

 print(ic.begin(), ic.end());

So the problem is, T cannot be deduced from the function argument. The Standard calls it non-deducible context. Here I've explained similar question in detail, read this:

Now the question is, how would you implement the function template? So here is one good solution:

template <class FwdIterator>
void print(FwdIterator start, FwdIterator end)
{
  for ( ;  start != end;  ++start)
  {
     std::cout << *start << '\n';
  }
}

If you pass a third argument as:

template <class FwdIterator>
void print(FwdIterator start, FwdIterator end, std::ostream &out)
{
  for ( ;  start != end;  ++start)
  {
     out << *start << '\n';
  }
}

then you can use this to print to file as well:

 print(ic.begin(), ic.end(), std::cout); //print to console


 std::ofstream file("file.txt")
 print(ic.begin(), ic.end(), file); //print to file
Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
0

The print function has to take the parameters as const references, else it can't be used with temporary values like those returned by begin() and end():

template <class T>
void print(const typename C<T>::iterator & start, const typename C<T>::iterator & end){
   ...
}
sth
  • 222,467
  • 53
  • 283
  • 367