vector<T>::iterator argument matching

L

lutorm

Hi all,
I'm having a problem writing template functions that take
vector<T>::iterator as arguments and I'm sure you guys can set me
straight. Like this:

#include<vector>
using namespace std;

template<typename T>
void test2(typename std::vector<T>::iterator b)
{};

void test() {
vector<double> v;
test2(v.begin());
}

If compiled with g++, I get

junk.cc:11: error: no matching function for call to
'test2(__gnu_cxx::__normal_iterator<double*, std::vector<double,
std::allocator<double> > >)'

If I specialize the test2 function with

void test2(std::vector<double>::iterator b)
{};

it compiles fine. I don't understand why it's not picking up the
templated version.

Regards,

/Patrik
 
M

mlimber

Hi all,
I'm having a problem writing template functions that take
vector<T>::iterator as arguments and I'm sure you guys can set me
straight. Like this:

#include<vector>
using namespace std;

template<typename T>
void test2(typename std::vector<T>::iterator b)
{};

void test() {
vector<double> v;
test2(v.begin());
}

If compiled with g++, I get

junk.cc:11: error: no matching function for call to
'test2(__gnu_cxx::__normal_iterator<double*, std::vector<double,
std::allocator<double> > >)'

If I specialize the test2 function with

void test2(std::vector<double>::iterator b)
{};

it compiles fine. I don't understand why it's not picking up the
templated version.

Regards,

/Patrik

It's a dependent name in the context of your function prototype, and so
it doesn't participate in name lookup. Try this:

template<class FwdIter>
void test2( FwdIter ) {}

If you want you can put some sort of static check (BOOST_STATIC_ASSERT
or Loki's STATIC_CHECK) in the body of the function to make sure you'll
get a compile-time error if the type is not a vector's iterator.

Cheers! --M
 
O

Old Wolf

template<typename T>
void test2(typename std::vector<T>::iterator b)
{};

void test() {
vector<double> v;
test2(v.begin());
}

If compiled with g++, I get

junk.cc:11: error: no matching function for call to
'test2(__gnu_cxx::__normal_iterator<double*, std::vector<double,
std::allocator<double> > >)'

Well, it works if you write:
test2<double>( v.begin() );

As to why your code doesn't work, I don't know exactly. But in
case nobody else knows either, here's my guess: the compiler
is trying to find a function with a parameter that matches:

__gnu_cxx::__normal_iterator<double*, std::vector<double,
std::allocator<double> > >

If it is to match this with:
std::vector<T>::iterator

then it would have to go through every possible option for
T and the see whether std::vector<T>::iterator matched the
type that it's searching for.

This kind of search is something that compilers normally
aren't expected to do (perhaps because it's slow, or
because it leads to fragile code).

The normal way to make a function that takes an iterator
is just to make the entire iterator type the template
parameter, and not worry about what sort of container
it is. But you might be able to do something similar to
what you are doing now, by using the advanced Boost
iterator concepts, which I'm not familiar with myself.
 
A

amparikh

mlimber said:
It's a dependent name in the context of your function prototype, and so
it doesn't participate in name lookup. Try this:

Its a dependent name alright, but I am not sure if that is the reason
the compiler is failing.
 
M

Michiel.Salters

Isnt std::vector<T>::iterator above actually form a non-deduced context
? I think that's the reason the compiler cant compile it.

It is.

The reason it's non-deduced is because in general Foo<T>::Bar and
Foo<U>::Bar can be the same type, say int. That means that you cannot
choose between T and U, if all you know is that the actual argument is
1.

Now, std::vector<T>::iterator is defined in the library in a way that
std::vector<T>::iterator != std::vector<U>::iterator if T != U, but the
core language doesn't have exceptions for this.
(std::vector<T>::const_iterator and std::set<const T>::const_iterator
might
actually be the same, which shows how tricky it is)

Regards,
Michiel Salters
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top