ivorynoise
ivorynoise

Reputation: 370

How to use templated iterators when value type of iterator is not know for a generalised STL Container?

I want to write templated function that

Here is the piece of code I have written but produces compilation error

template <template<typename, typename> class Container, 
            typename Value, 
            typename Allocator = std::allocator<Value> >
void printContainer(Container<Value, Allocator>::iterator itBegin,
                    Container<Value, Allocator>::iterator itEnd)
{
        copy(itBegin, itEnd, ostream_iterator<Value>(cout, " "));
        cout << endl;
}

Error produced are :

  error 1: variable or field ‘printContainer’ declared void
  void printContainer(Container<Value, Allocator>::iterator itBegin,
                                                   ^
  error 2: expected ‘)’ before ‘itBegin’
  void printContainer(Container<Value, Allocator>::iterator itBegin,
                                                            ^
  error 3: expected ‘)’ before ‘itEnd’
       Container<Value, Allocator>::iterator itEnd)
                                             ^
 p00441.cpp: In function ‘int main()’:
 p00441.cpp:10:39: error: ‘printContainer’ was not declared in this scope
   printContainer(inp.begin(), inp.end());

Another snippet I wrote is

template<typename InputIterator>
void printContainer(InputIterator itBegin, InputIterator itEnd){
        //Trial 1
        copy(itBegin, itEnd, ostream_iterator< iterator_traits<ForwardIterator1>::value_type>(cout, " "));

        //Trial 2
        copy(itBegin, itEnd, ostream_iterator<value_type(itBegin)*>(cout, " "));
        cout << endl;
}

Error produced are :

error 1: ‘ForwardIterator1’ was not declared in this scope
   copy(itBegin, itEnd, ostream_iterator< iterator_traits<ForwardIterator1>::value_type>(cout, " "));
                                                          ^
error 2: template argument 1 is invalid
   copy(itBegin, itEnd, ostream_iterator< iterator_traits<ForwardIterator1>::value_type>(cout, " "));
                                                                          ^
error 3: template argument 1 is invalid
   copy(itBegin, itEnd, ostream_iterator< iterator_traits<ForwardIterator1>::value_type>(cout, " "));
                                                                                       ^
error 3: type/value mismatch at argument 1 in template parameter list for ‘template<class _Tp, class _CharT, class _Traits> class std::ostream_iterator’
   copy(itBegin, itEnd, ostream_iterator<value_type(itBegin)*>(cout, " "));
                                                             ^
error 4:   expected a type, got ‘(value_type(itBegin) * <expression error>)’

Please elaborate what errors mean and their cause of occurrence. Also suggest how to achieve the desired goal.

I will be grateful if you could suggest some sources for a novice to understand iterators.

Upvotes: 1

Views: 389

Answers (1)

rainer
rainer

Reputation: 7109

Regarding your first question, you can simply use the iterator as the template type and use iterator::value_type:

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <iterator>

using namespace std;

template <typename Iterator>
void printContainer(Iterator itBegin,
                    Iterator itEnd)
{
        copy(itBegin, itEnd, ostream_iterator<typename Iterator::value_type>(cout, " "));
        cout << endl;
}

int main() {
    vector<int> v{1, 2, 3, 4, 5, 6};
    list<int>   l{1, 2, 3, 4, 5, 6};
    printContainer(begin(v), end(v));
    printContainer(begin(l), end(l));

    return 0;
}

https://ideone.com/DhUQ1t

Using iterator_traits also works and is a better solution since it will also work for pointers (that naturally do not have the value_type member; thanks to Jarod42 for pointing this out):

template <typename Iterator>
void printContainer(Iterator itBegin,
                    Iterator itEnd)
{
        copy(itBegin, itEnd, ostream_iterator<typename iterator_traits<Iterator>::value_type>(cout, " "));
        cout << endl;
}

https://ideone.com/8N0ook

Starting with C++14, you can also use decltype and decay_t:

template <typename Iterator>
void printContainer(Iterator itBegin,
                    Iterator itEnd)
{
        copy(itBegin, itEnd, ostream_iterator<decay_t<decltype(*itBegin)>>(cout, " "));
        cout << endl;
}

https://ideone.com/7MBsiL


Regarding your other tries, there's no ForwardIterator1 defined in your function and value_type is a typedef, not a function.

Upvotes: 5

Related Questions