473,508 Members | 2,104 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Mixing STL maps/vectors with templates

5 New Member
This is a really annoying thing to look up in Google because all pages that mention STL maps or vectors will most likely also contain the word "template". So maybe this question has been asked before, but it's nearly impossible to find.

I'm having trouble using STL vectors, maps, ... in templated functions, when the templated class is a template parameter of the map too.
Below is a (cannibalized) example of a class 'Model' which contains several STL maps with different objects. I want to perform a similar operation on these different maps. Instead of writing nearly similar methods for each type of map, it would be much nicer to have a single template method. In the example below, the findStuff method returns a pointer to the object to be found, or NULL if it can't be found. This is of course rather useless because I could just use find() directly, but it's just an illustration.
Aside from having to add the 'typename' word which I'm not familiar with, the code compiles fine until I try to use findStuff, like:
Expand|Select|Wrap|Line Numbers
  1. string sName("someGroup");
  2. Group *theGroup = findStuff( sName, m_mGroups );
This produces a linking error in GCC (4.1.1):
undefined reference to `Group* Model::findStuff<Group>(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, Group, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const>, std::allocator<std:: pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, Group> > >&)'

I'm not too familiar with templates, so maybe I'm just making a silly error? However, it appears the template is correctly instantiated, only it can't be found by the linker?

Expand|Select|Wrap|Line Numbers
  1. /* Class code */
  2. Class Model
  3. {
  4. public:
  5.   map<const string, Group> m_mGroups;
  6.   map<const string, Shape> m_mShapes;
  7.  
  8.   template <class T>
  9.   T * findStuff( const string &sName, map<const string, T> &mMap );
  10. };
  11.  
  12. template <class T>
  13. T * Model::findStuff( const string &sName, map<const string, T> &mMap )
  14. {
  15.     typename map<const string, T>::iterator it = mMap.find(sName);
  16.     if( it == mMap.end() )
  17.         return NULL;
  18.     return &(it->second);
  19. }
Feb 9 '07 #1
5 1766
AdrianH
1,251 Recognized Expert Top Contributor
Hi,

I'm sorry, but I'm not sure what you are trying to do. The code is incomplete (i.e. not compliable) and I don't have time to figure out what you are attempting. Oh, wait a minute, perhaps you were trying to do this?

Expand|Select|Wrap|Line Numbers
  1. #include "stdafx.h"
  2.  
  3. #include <string>
  4. #include <map>
  5. using namespace std;
  6.  
  7. struct Group{};
  8. struct Shape{};
  9.  
  10. class Model
  11. {
  12. public:
  13.   map<const string, Group> m_mGroups;
  14.   map<const string, Shape> m_mShapes;
  15.  
  16.   template <class T>
  17.   T * findStuff( const string &sName, map<const string, T> &mMap );
  18.     void fn()
  19.     {
  20.         string sName("someGroup");
  21.         Group *theGroup = findStuff( sName, m_mGroups );
  22.     }
  23. };
  24.  
  25. template <class T>
  26. T * Model::findStuff( const string &sName, map<const string, T> &mMap )
  27. {
  28.     typename map<const string, T>::iterator it = mMap.find(sName);
  29.     if( it == mMap.end() )
  30.         return NULL;
  31.     return &(it->second);
  32. }
  33.  
  34. int main(int argc, char* argv[])
  35. {
  36.     Model a;
  37.     a.fn();
  38.     return 0;
  39. }
  40.  
This compiled and linked correctly (although there were lots of warning about identifiers being truncated due to being longer than 255 characters, but this is normal and can be ignored for the most part).

If this is what you are attempting, then I don't see why it doesn't link on your system. If it is not, please post a minimal, but compliable set of code so that it can be independently verified and tested and I will see what I can do.


Adrian
Feb 9 '07 #2
DrLex
5 New Member
Hi,

I'm sorry, but I'm not sure what you are trying to do. The code is incomplete (i.e. not compliable) and I don't have time to figure out what you are attempting. Oh, wait a minute, perhaps you were trying to do this?
Yes, that's roughly what I try to do, except that findStuff() would be called in a derived class of Model. The funny thing is that your code compiles on my system as well. So I did some more tests and it appears that the linking error occurs as soon as I put the definition of findStuff in a different file than the one in which it is called. For instance:
File "model.h":
Expand|Select|Wrap|Line Numbers
  1. #ifndef MODEL_H
  2. #define MODEL_H
  3.  
  4. #include <map>
  5. #include <string>
  6. using namespace std;
  7.  
  8. struct Group{};
  9.  
  10. class Model
  11. {
  12. public:
  13.     map<const string, Group> m_mGroups;
  14.  
  15.     template <class T>
  16.     T * findStuff( const string &sName, map<const string, T> &mMap );
  17.     void fn()
  18.     {
  19.         string sName("someGroup");
  20.         Group *theGroup = findStuff( sName, m_mGroups );
  21.     }
  22. };
  23.  
  24. #endif // MODEL_H
File "model.cpp":
Expand|Select|Wrap|Line Numbers
  1. #include "model.h"
  2.  
  3. template <class T>
  4. T * Model::findStuff( const string &sName, map<const string, T> &mMap )
  5. {
  6.     typename map<const string, T>::iterator it = mMap.find(sName);
  7.     if( it == mMap.end() )
  8.         return NULL;
  9.     return &(it->second);
  10. }
File "main.cpp":
Expand|Select|Wrap|Line Numbers
  1. #include "model.h"
  2.  
  3. int main(int argc, char* argv[])
  4. {
  5.     Model a;
  6.     a.fn();
  7.     return 0;
  8. }
If I would define findStuff() in model.h, it works. But that's no solution in my case because I'd like to use it in a derived class of Model. And I simply want to know why it doesn't work of course :)
Feb 9 '07 #3
mambazo
1 New Member
You should read this:

http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html

Most of what is said applies to Visual Studio and other popular C++ compilers. Basically, the bottom line is that you _have_ to put the templated definitions in your header file, so that the entire definition is available at instantiation.

Also, I don't see why this is a problem if you want to call the function from a derived class.
Feb 9 '07 #4
DrLex
5 New Member
Most of what is said applies to Visual Studio and other popular C++ compilers. Basically, the bottom line is that you _have_ to put the templated definitions in your header file, so that the entire definition is available at instantiation.
OK, it's not a nice & clean solution, but it works. Thanks for pointing this out.

Also, I don't see why this is a problem if you want to call the function from a derived class.
This is indeed not a problem, my assumption that the definition must be in the very same file as where the method is called, was wrong (luckily).
Feb 9 '07 #5
AdrianH
1,251 Recognized Expert Top Contributor
Most of what is said applies to Visual Studio and other popular C++ compilers. Basically, the bottom line is that you _have_ to put the templated definitions in your header file, so that the entire definition is available at instantiation.
Yeah, this is a limitation of most C++ compilers. I don't know of one that actually allows you to do it any other way. It has to do with the format of the object files generated. They aren't able to store the necessary information. Sorta the same with inlining, though I think that compilers are starting to do a better job about that without having to put the inlined code available to everyone.


Adrian
Feb 11 '07 #6

Sign in to post your reply or Sign up for a free account.

Similar topics

10
15805
by: Michael Aramini | last post by:
I need to represent 1D and 2D arrays of numeric or bool types in a C++ program. The sizes of the arrays in my intended application are dynamic in the sense that they are not known at compile time,...
12
1636
by: Fred Ma | last post by:
Hello, I was looking at Meyers's "Effective STL", item 23 about choosing between vectors and maps (at least that the choice for me). In many cases, using sorted vectors is faster for lookups. ...
19
1924
by: nick | last post by:
The attached program is fine, but I need to create vectors for each AcctExample object. I know that I can do the following: vector<AcctExample> example which makes a vector of AcctExample objects...
5
1533
by: roberts.noah | last post by:
It is my understanding that if you contain vectors or maps you don't need to create copy constructors because the default calls that constructor. It is my understanding that if you use these types...
10
1871
by: ballpointpenthief | last post by:
How good is the C language for implementing maps, filters and accumulators? SCHEME programmers would be able to pass procedures as arguments quite easily, whereas C programmers would - I guess -...
3
4681
by: frank | last post by:
Hi I've got aplication, which one is written in unmanaged c++ with stl, i've made for it gui in managed c++. Problem becomes when I'm starting to filling up for example datagrids, when I'm...
5
1879
by: pallav | last post by:
I have a map like this: typedef boost::shared_ptr<NodeNodePtr; typedef std::vector<NodePtrNodeVecPtr; typedef std::map<std::string, NodePtrNodeMap; typedef std::map<std:string,...
3
6431
by: jacek.dziedzic | last post by:
Hi! What is the canonical way of finding an intersection of two std::maps? i.e. I have std::map<whatever,size_tmap1; std::map<whatever,size_tmap2; .... and I need an std::vector...
1
2038
by: Rob | last post by:
How would I do this? I want to be able to handle vectors of many different types of data and vectors that can contain any number of other vectors of data. Currently, I have a templated...
0
7125
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7388
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
7499
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5631
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5055
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4709
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3199
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3186
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
767
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.