template-nested STL iterator question

C

chriscorbell

I'm curious about what appears to be a restriction on using an STL
container inside a user-defined template, esp. using an iterator to
such a container. It's not clear to me if this is a general
template/language restriction, and STL iterator limitation, or if I'm
just going about it wrong.

I'm declaring a template which uses a std::map to store references to
the template type, e.g.

template template <typename T>
class MyClass
{
public:
// ...
private:
std::map<std::string, T*> m_objectMap;
};

This compiles fine. However if I have a declaration of an iterator to
this map in a method of my class, the compile fails, e.g.

template template <typename T>
class MyClass
{
public:
T* Lookup(std::string)
{
T* pT = NULL;
std::map<std::string, T*>::iterator iTptr = m_objectMap.find();
if(iTptr != m_objectMap.end())
pT = *iTptr;
return pT;
}
private:
std::map<std::string, T*> m_objectMap;
};

Is there a correct way to accomplish this? If not, anyone know the
rationale?

The kludgy workaround I'm using is to use void * instead of T* for the
std::map and static-cast it.

- Chris
 
V

Victor Bazarov

chriscorbell said:
I'm curious about what appears to be a restriction on using an STL
container inside a user-defined template, esp. using an iterator to
such a container. It's not clear to me if this is a general
template/language restriction, and STL iterator limitation, or if I'm
just going about it wrong.

I'm declaring a template which uses a std::map to store references to
the template type, e.g.

template template <typename T>
class MyClass
{
public:
// ...
private:
std::map<std::string, T*> m_objectMap;
};

This compiles fine. However if I have a declaration of an iterator to
this map in a method of my class, the compile fails, e.g.

template template <typename T>
class MyClass
{
public:
T* Lookup(std::string)
{
T* pT = NULL;
std::map<std::string, T*>::iterator iTptr = m_objectMap.find();

if(iTptr != m_objectMap.end())
pT = *iTptr;
return pT;
}
private:
std::map<std::string, T*> m_objectMap;
};

Is there a correct way to accomplish this? If not, anyone know the
rationale?

Read the FAQ. Dependent names are described in the 'Templates' section.
The kludgy workaround I'm using is to use void * instead of T* for the
std::map and static-cast it.

That's a BAD IDEA(tm).

V
 
J

Jonathan Mcdougall

chriscorbell said:
I'm curious about what appears to be a restriction on using an STL
container inside a user-defined template, esp. using an iterator to
such a container. It's not clear to me if this is a general
template/language restriction, and STL iterator limitation, or if I'm
just going about it wrong.

I'm declaring a template which uses a std::map to store references to
the template type, e.g.

template template <typename T>
class MyClass
{
public:
// ...
private:
std::map<std::string, T*> m_objectMap;
};

This compiles fine. However if I have a declaration of an iterator to
this map in a method of my class, the compile fails, e.g.

template template <typename T>
class MyClass
{
public:
T* Lookup(std::string)
{
T* pT = NULL;
std::map<std::string, T*>::iterator iTptr = m_objectMap.find();

Make this

typename std::map<std::string, T*>::iterator iTptr =
m_objectMap.find();

Because T is a template argument, the compiler has no way, when it
parses this statement, to know what it is. That means it cannot know
what "iterator" is in this context (std::map could be specialized for a
given T and that specialization could have no member "iterator" or
"iterator" could even be an object and not a type). By adding
"typename", you specify the compiler that "iterator" is a type name
inside std::map. It'll double check later.


Jonathan
 
A

Alf P. Steinbach

* chriscorbell:
I'm curious about what appears to be a restriction on using an STL
container inside a user-defined template, esp. using an iterator to
such a container. It's not clear to me if this is a general
template/language restriction, and STL iterator limitation, or if I'm
just going about it wrong.

I'm declaring a template which uses a std::map to store references to
the template type, e.g.

template template <typename T>
class MyClass
{
public:
// ...
private:
std::map<std::string, T*> m_objectMap;
};

This compiles fine.

I get a syntax error on the first line.

Which compiler is it that accepts the above?

However if I have a declaration of an iterator to
this map in a method of my class, the compile fails, e.g.

template template <typename T>
class MyClass
{
public:
T* Lookup(std::string)
{
T* pT = NULL;
std::map<std::string, T*>::iterator iTptr = m_objectMap.find();
if(iTptr != m_objectMap.end())
pT = *iTptr;
return pT;
}
private:
std::map<std::string, T*> m_objectMap;
};

Curiously, as long as the Lookup function isn't actualy called, with the
first line corrected this (incorrectly) compiles fine with MSVC 7.1.

Is there a correct way to accomplish this?

Presumably you intended to (1) pass that string argument as 'std::string
const& s', (2) supply some argument to 'find', e.g. '.find(s)', and (3)
access the second field of the found pair, 'pT = iTptr->second'.

If not, anyone know the rationale?

For what?

The kludgy workaround I'm using is to use void * instead of T* for the
std::map and static-cast it.

That shouldn't work.
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top