Reputation: 1
I am new to using templates and am required to use a template to do something, but don't know how to call the templated function. It's probably soething simple, but I can't see it.
template<class It, class T>
// iterator and value_type of *It
void Calc(It begin, It end, std::pair<int, int> &out)
{
std::vector<It>::iterator iter;
std::map<int, int> StartMap;
std::map<int, int>::reverse_iterator rit;
int sum, start, stop, count;
start = stop = 1;
count = sum = 0;
for(iter = begin; iter != end; iter++ )
{
sum += iter;
count++;
stop++;
if(sum <= 0)
{
// store original start
StartMap.insert(start, count);
// set new start position
start = stop;
}
}
// set iterator to highest value
rit = StartMap.rbegin();
start = rit->first;
stop = start + rit->second;
out.insert(start, stop);
}
but not sure how I call it with 2 std::vector iterators. I've tried this
void doSomething(std::vector<int>& stopsVec)
{
std::pair<int, int> out;
Calc<std::vector<int>::iterator, std::pair<int, int>>(stopsVec.begin(), stopsVec.end(), &out);
}
Upvotes: 0
Views: 268
Reputation: 373172
You don't need to explicitly pass the type being iterated over as a template argument. The STL designers were quite wise and realized that this often comes up, and there's a (not very pretty but entirely correct) way to introspect on the type of an iterator to get it's underlying type as follows:
typedef typename std::iterator_traits<It>::value_type value_type;
Once you've done this, you can use the name value_type to refer to the type being iterated over. This lets you rewrite the template function as
template <typename It>
void Calc(It begin, It end, std::pair<int, int>& out) {
typedef typename std::iterator_traits<It>::value_type value_type;
/* ... Rest of the code, now using this type ... */
}
And to seal the deal, now that there aren't any auxiliary types required, you can call the function directly as
std::vector<int> v = /* ... */
std::pair<int, int> result;
Calc(v.begin(), v.end(), result);
Hopefully this is easier to read and write!
Upvotes: 0
Reputation: 9172
void doSomething(std::vector<int>& stopsVec)
{
std::pair<int, int> out;
Calc<std::vector<int>::iterator, std::pair<int, int> >
(stopsVec.begin(), stopsVec.end(), out); // not &out
}
Calc
takes a reference to std::pair<int, int>
, so you want to just give it out
. Passing &out
tries to pass a pointer to a pair - which won't work.
EDIT
assuming the signature is actually:
template<class It>
void Calc(It begin, It end, std::pair<int, int> &out)
You can call it with:
Calc(stopsVec.begin(), stopsVec.end(), out);
The compiler can deduce the correct template type from the parameters, without requiring you to specify them between <>
EDIT
Keith makes a good point below. That's another compilation error you would have here. Also note that:
sum += iter;
does not do what you want. you probably meant:
sum += *iter;
But since sum
is an int, and iter
is a template type, this is not really a general-purpose template method. It's really only going to work for iterators over numeric types.
And, one other issue:
Calc<std::vector<int>::iterator, std::pair<int, int> > // use a space
(stopsVec.begin(), stopsVec.end(), out);
instead of
Calc<std::vector<int>::iterator, std::pair<int, int>> // ">>" is shift operator
(stopsVec.begin(), stopsVec.end(), out);
You need a space between the closing >
signs in order to have template syntax. Otherwise you're doing bitshift (or stream extraction), and the compiler will get confused because nothing will make sense from that point on.
Upvotes: 4
Reputation: 6834
Note that:
template<class It, class T>
void Calc(It begin, It end, std::pair<int, int> &out)
{
std::vector<It>::iterator iter;
for(iter = begin; iter != end; iter++ )
is wrong. It should probably be:
template<class It, class T>
void Calc(It begin, It end, std::pair<int, int> &out)
{
It iter;
// etc.
for(iter = begin; iter != end; iter++ )
But also note that in C++, it is generally preferred to follow the 'declaration is initialisation' approach, so this becomes:
template<class It, class T>
void Calc(It begin, It end, std::pair<int, int> &out)
{
// etc.
for(It iter = begin; iter != end; iter++ )
Upvotes: 0