Agnius Vasiliauskas
Agnius Vasiliauskas

Reputation: 11267

templates accepting two iterators

Why ordinary algorithm template is designed so that it accepts two iterators instead of pair of these iterators ? Consider this example:

#include <iostream>
#include <iterator>
#include <vector>

using namespace std;

template <typename Range, typename OutputIterator> 
void copy2 (Range r, OutputIterator o) {
     copy (r.first, r.second, o);
}

template <typename iter1, typename iter2> 
pair<typename iter1, typename iter2> Range(iter1 start, iter2 end) {
    return make_pair(start, end);
}

int main()
{
    vector<int> myvector;
    myvector.push_back(3);
    myvector.push_back(2);
    myvector.push_back(1);

    // ordinary algorithm template accepts two iterators
    copy(myvector.begin(), 
         myvector.end(), 
         ostream_iterator<int> (cout,"\n") );

    // this template accepts iterator Range
    copy2(Range(myvector.begin(),myvector.end()),
          ostream_iterator<int> (cout,"\n"));
}

What are reasons of copy() being better than copy2() [other than copy2() call verbosity]

EDIT: I cut down verbosity of copy2() by a great amount as DeadMG suggested.

Upvotes: 0

Views: 185

Answers (4)

Connman
Connman

Reputation: 158

In copy2 there's a little extra overhead from having to construct the pair from your two iterators. It may not be much but there's no reason to add extra computations if they're not necessary.

Also, the benefits of keeping code as easy to understand as possible shouldn't be underestimated.

Upvotes: 0

Mark B
Mark B

Reputation: 96233

I assume it's so that if you already have single iterators you don't have to construct a pair to call the algorithm, and that it keeps all the arguments to the algorithm consistent: An iterator of some sort (and possibly a predicate).

Upvotes: 0

Puppy
Puppy

Reputation: 146910

Really? There isn't one. The Standard library only has the notion of iterators because, as far as I know, nobody came up with ranges before it was Standardised. Many people think that it could be vastly improved by using ranges. Secondly, you can easily improve the verbosity of #2 with a little extra pre-written boiler.

template<typename T> std::pair<typename T::const_iterator, typename T::const_iterator> all(const T& t) {
    return std::make_pair(t.begin(), t.end());
}
template<typename T> std::pair<typename T::iterator, typename T::iterator> all( T& t) {
    return std::make_pair(t.begin(), t.end());
}

copy2(all(myvector), ostream_iterator<int>(cout, "\n"));

Upvotes: 1

MarkD
MarkD

Reputation: 4944

I look at it as keeping things simple. What does wrapping your iterators in another container give you, other than a smaller signature for your copy2 function? (Personally, I don't see any advantage to wrapping it in a pair, so it is just more code to write to call the function)

And looking at the example code you posted, the original copy call is (IMO) much more readable than the copy2 call.

Upvotes: 0

Related Questions