Help | Site Map
Connecting Tech Pros Worldwide
 
 
LinkBack Thread Tools
  #1  
Old August 10th, 2006, 11:35 AM
devmentee@hotmail.com
Guest
 
Posts: n/a
Default map containing a string key and a templated value...

Hello,

I am trying to create a map/dictionary where the type of key is known
ie std::string, but the value could be of any built in type. ie. int,
double etc. (something along the lines of map<string, Twhere T is
template argument)

To hold the value type I have something like:

template<class T>
struct Data
{
T value;
}

Now I am trying to declare a map as below:

std::map<std::string, Data>;

this doesn't/wouldn't work and I don't know how to declare it??

if I have a method which has to pass in this map as a parameter, how
would I do it??
e.g Foo(std::map<string, Dataparam ) doesn't work and I don't expect
it to either

Can someone please help!

  #2  
Old August 10th, 2006, 11:45 AM
Thomas J. Gritzan
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

devmentee@hotmail.com schrieb:
Quote:
Hello,
>
I am trying to create a map/dictionary where the type of key is known
ie std::string, but the value could be of any built in type. ie. int,
double etc. (something along the lines of map<string, Twhere T is
template argument)
>
To hold the value type I have something like:
>
template<class T>
struct Data
{
T value;
}
>
Now I am trying to declare a map as below:
>
std::map<std::string, Data>;
>
this doesn't/wouldn't work and I don't know how to declare it??
If you want a heterogenous container, you need run-time polymorphism;
you can't do it with templates alone.

That is, use a virtual base class and templated sub-classes which hold
the actual type.

The easiest way would be to use either of boost::any or
boost::variant<>, they both do something similar:

std::map<std::string, boost::anymapOfAnyType;

--
Thomas
  #3  
Old August 10th, 2006, 11:45 AM
devmentee@hotmail.com
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

Many Thanks for your prompt reply! Can I please ask following

1) will boost::any let me store any type including built-in types and
are there good examples on their site with regards to this particular
feature?
2) when you said "That is, use a virtual base class and templated
sub-classes which hold the actual type." - did you mean declaring a
something like map<string, base*>? would the base have to be declared
as a template too?

  #4  
Old August 10th, 2006, 01:15 PM
zhao.kaiyong@gmail.com
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...


devmentee@hotmail.com wrote:
Quote:
Hello,
>
I am trying to create a map/dictionary where the type of key is known
ie std::string, but the value could be of any built in type. ie. int,
double etc. (something along the lines of map<string, Twhere T is
template argument)
>
To hold the value type I have something like:
>
template<class T>
struct Data
{
T value;
}
>
Now I am trying to declare a map as below:
>
std::map<std::string, Data>;
>
this doesn't/wouldn't work and I don't know how to declare it??
>
if I have a method which has to pass in this map as a parameter, how
would I do it??
e.g Foo(std::map<string, Dataparam ) doesn't work and I don't expect
it to either
>
Can someone please help!
I think you can use

std::map<std::string, Data*>;

  #5  
Old August 10th, 2006, 01:15 PM
Thomas J. Gritzan
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

devmentee@hotmail.com schrieb:
Quote:
Many Thanks for your prompt reply! Can I please ask following
>
1) will boost::any let me store any type including built-in types and
are there good examples on their site with regards to this particular
feature?
There are some restrictions for the types documented, but you can store
all built-in types. For the examples, look for yourself:

http://www.boost.org/doc/html/any.html
Quote:
2) when you said "That is, use a virtual base class and templated
sub-classes which hold the actual type." - did you mean declaring a
something like map<string, base*>? would the base have to be declared
as a template too?
Yes, I meant something like that, and no, the base class should better
not be a template. You can't put a templated class or pointer to
templated class in a container, you can do this only with a concrete
instantiation of the template. That is why you need a base class.

The boost::any class does this for you, and it works as a simple smart
pointer, so you don't even have to store raw pointers in the map.

--
Thomas
  #6  
Old August 10th, 2006, 02:05 PM
Michiel.Salters@tomtom.com
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

zhao.kaiyong@gmail.com wrote:
Quote:
devmentee@hotmail.com wrote:
Quote:
Hello,

I am trying to create a map/dictionary where the type of key is known
ie std::string, but the value could be of any built in type. ie. int,
double etc. (something along the lines of map<string, Twhere T is
template argument)
[...]
Quote:
>
I think you can use
>
std::map<std::string, Data*>;
No. Data is not a type. It's a template. Any instantiation of the Data
template,
e.g. Data<int>, is a type. The arguments to the std::map template are
two
types. [1] Hence, you can write std::map<std::string, Data<int
MyMap;
With the proposed Data template that of course adds little value.

The better solution is already given. (Use boost)

HTH,
Michiel Salters

[1] Not counting the third argument, because it has a default
(std::allocator)

  #7  
Old August 10th, 2006, 02:35 PM
devmentee@hotmail.com
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

Looks like there is really no way in C++ to have a generic type like
that in a map. Templates solve half the problem but don't go all the
way.. :-(

it is not possible to use std::map<std::string, Data*for the reasons
mentioned by Michiel.
What I can do is make Data a base class, then derive templated class
from data and instantiate these, and store pointers to these in the
above map. All sounds like too much effort!
I like the idea of using boost but I am not allowed to use it in my
project :-(

Thanks to all of you again...

  #8  
Old August 10th, 2006, 02:35 PM
mlimber
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

devmentee@hotmail.com wrote:
Quote:
Hello,
>
I am trying to create a map/dictionary where the type of key is known
ie std::string, but the value could be of any built in type. ie. int,
double etc. (something along the lines of map<string, Twhere T is
template argument)
>
To hold the value type I have something like:
>
template<class T>
struct Data
{
T value;
}
>
Now I am trying to declare a map as below:
>
std::map<std::string, Data>;
>
this doesn't/wouldn't work and I don't know how to declare it??
>
if I have a method which has to pass in this map as a parameter, how
would I do it??
e.g Foo(std::map<string, Dataparam ) doesn't work and I don't expect
it to either
>
Can someone please help!
Just to be clear: do you want to store actual values of different types
in the same map (if so, use boost::any as suggested by others), or are
you just wanting to have a "template typedef" that defines only one of
the existing tempalte parameters like this:

template<typename T>
struct MyMap
{
typedef std::map<std::string,Ttype;
};

MyMap<int>::type intMap;
MyMap<float>::type floatMap;

Cheers! --M

  #9  
Old August 10th, 2006, 02:45 PM
Victor Bazarov
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

devmentee@hotmail.com wrote:
Quote:
[...] Templates solve half the problem but don't go all the
way.. :-(
>
[...] All sounds like too much effort!
>
Life... First you suffer through it, then you die...


  #10  
Old August 10th, 2006, 03:25 PM
devmentee@hotmail.com
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

Rather die than use VB or C# :-P

To the previous poster, no I did think of template typedef but that
only works if i want one specific type. I want a map which stores any
built in data type ie. int, double etc...
so something like map<string, object) in java or other similar
languages...

Victor Bazarov wrote:
Quote:
devmentee@hotmail.com wrote:
Quote:
[...] Templates solve half the problem but don't go all the
way.. :-(

[...] All sounds like too much effort!
>
Life... First you suffer through it, then you die...
  #11  
Old August 10th, 2006, 03:55 PM
mlimber
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

devmentee@hotmail.com wrote:
Quote:
I like the idea of using boost but I am not allowed to use it in my
project :-(
So go ahead and reinvent the wheel: write a discriminated union of your
own, and you'll acheive the same effect.

Cheers! --M

  #12  
Old August 11th, 2006, 06:15 PM
Diego Martins
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

mlimber wrote:
Quote:
devmentee@hotmail.com wrote:
Quote:
Rather die than use VB or C# :-P

To the previous poster, no I did think of template typedef but that
only works if i want one specific type. I want a map which stores any
built in data type ie. int, double etc...
so something like map<string, object) in java or other similar
languages...
>
Quote:
I like the idea of using boost but I am not allowed to use it in my
project :-(
>
So go ahead and reinvent the wheel: write a discriminated union of your
own, and you'll acheive the same effect.
>
Cheers! --M
If you like the Java style, create an Object class and make subclasses
that will behave like wrappers of built-in data types (Integer, Bool,
etc.)

map<string,Object *will be your map type and you can use RTTI to
determine how to access the data

struct Object {
virtual ~Object() {} // allows delete by Object pointer
};

struct Integer: public Object { int data; Integer(int d): data(d) {}
};
struct Bool: public Object { bool data; Bool(bool d): data(d) {} };
....

of course a template can save you from the dirty work
template<typename T>
struct DataWrapper: public Object { T data; DataWrapper(T d): data(d)
};

....

map<string,Object *suckMap;
suckMap["integer"] = new Integer(10);
suckMap["a little bool"] = new Bool(false);
suckMap["other bool"] = new DataWrapper<bool>(false);
....
if( DataWrapper<long* t = dynamic_cast<DataWrapper<long>
Quote:
>(suckMap["lonely long") ) {
cout << t->data << "is a long value" << endl;
}

Hope this helps

Diego Martins

  #13  
Old August 11th, 2006, 06:55 PM
mlimber
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

Diego Martins wrote:
Quote:
If you like the Java style, create an Object class and make subclasses
that will behave like wrappers of built-in data types (Integer, Bool,
etc.)
This is generally frowned upon. See the reasons why here:

http://www.research.att.com/~bs/bs_faq2.html#object

and

http://www.artima.com/intv/goldilocks2.html
Quote:
>
map<string,Object *will be your map type and you can use RTTI to
determine how to access the data
>
struct Object {
virtual ~Object() {} // allows delete by Object pointer
};
>
struct Integer: public Object { int data; Integer(int d): data(d) {}
};
struct Bool: public Object { bool data; Bool(bool d): data(d) {} };
...
>
of course a template can save you from the dirty work
template<typename T>
struct DataWrapper: public Object { T data; DataWrapper(T d): data(d)
};
>
...
>
map<string,Object *suckMap;
suckMap["integer"] = new Integer(10);
suckMap["a little bool"] = new Bool(false);
suckMap["other bool"] = new DataWrapper<bool>(false);
...
if( DataWrapper<long* t = dynamic_cast<DataWrapper<long>
Quote:
(suckMap["lonely long") ) {
cout << t->data << "is a long value" << endl;
}
Assuming you fix the syntax errors in this code, it will still not
likely do what you were attempting since std::map's bracket operator
will actually *insert* a default-initialized value (read: null pointer)
with the key "lonely long" if the key cannot be found in the map (cf.
footnote 3 here: http://www.sgi.com/tech/stl/Map.html#3).

This won't cause an immediate problem since dynamic_cast will either
succeed (if the map element with that key has a DataWrapper<long>* as
its value) or will return null and not enter the body of the
if-statement (because the type is different or because the pointer is
null). But the use of std::map<>::operator[]() could potentially insert
a null pointer, which the user of the map may not expect and which you
probably did not intend. This could be fixed by using
std::map<>::find() (or similar) to do the look-up instead.

Cheers! --M

  #14  
Old August 14th, 2006, 07:45 PM
Diego Martins
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...


mlimber wrote:
Quote:
Diego Martins wrote:
Quote:
If you like the Java style, create an Object class and make subclasses
that will behave like wrappers of built-in data types (Integer, Bool,
etc.)
>
This is generally frowned upon. See the reasons why here:
>
http://www.research.att.com/~bs/bs_faq2.html#object
>
and
>
http://www.artima.com/intv/goldilocks2.html
>
Quote:

map<string,Object *will be your map type and you can use RTTI to
determine how to access the data

struct Object {
virtual ~Object() {} // allows delete by Object pointer
};

struct Integer: public Object { int data; Integer(int d): data(d) {}
};
struct Bool: public Object { bool data; Bool(bool d): data(d) {} };
...

of course a template can save you from the dirty work
template<typename T>
struct DataWrapper: public Object { T data; DataWrapper(T d): data(d)
};

...

map<string,Object *suckMap;
suckMap["integer"] = new Integer(10);
suckMap["a little bool"] = new Bool(false);
suckMap["other bool"] = new DataWrapper<bool>(false);
...
if( DataWrapper<long* t = dynamic_cast<DataWrapper<long>
Quote:
>(suckMap["lonely long") ) {
cout << t->data << "is a long value" << endl;
}
>
Assuming you fix the syntax errors in this code, it will still not
likely do what you were attempting since std::map's bracket operator
will actually *insert* a default-initialized value (read: null pointer)
with the key "lonely long" if the key cannot be found in the map (cf.
footnote 3 here: http://www.sgi.com/tech/stl/Map.html#3).
>
This won't cause an immediate problem since dynamic_cast will either
succeed (if the map element with that key has a DataWrapper<long>* as
its value) or will return null and not enter the body of the
if-statement (because the type is different or because the pointer is
null). But the use of std::map<>::operator[]() could potentially insert
a null pointer, which the user of the map may not expect and which you
probably did not intend. This could be fixed by using
std::map<>::find() (or similar) to do the look-up instead.
>
Cheers! --M
thanks for the find() advice :-)

personally, I dislike this java-style. I only presented a possible
working solution for a "generic" container

# A "universal" class encourages sloppy thinking about types and
interfaces and leads to excess run-time checking.
# Using a universal base class implies cost: Objects must be
heap-allocated to be polymorphic; that implies memory and access cost.
Heap objects don't naturally support copy semantics. Heap objects don't
support simple scoped behavior (which complicates resource management).
A universal base class encourages use of dynamic_cast and other
run-time checking.

these issues are right, but what is the alternative if we really need a
generic container?

cya
Diego Martins

  #15  
Old August 14th, 2006, 08:45 PM
mlimber
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

Diego Martins wrote:
Quote:
mlimber wrote:
Quote:
Diego Martins wrote:
Quote:
If you like the Java style, create an Object class and make subclasses
that will behave like wrappers of built-in data types (Integer, Bool,
etc.)
This is generally frowned upon. See the reasons why here:

http://www.research.att.com/~bs/bs_faq2.html#object

and

http://www.artima.com/intv/goldilocks2.html
>
personally, I dislike this java-style. I only presented a possible
working solution for a "generic" container
>
# A "universal" class encourages sloppy thinking about types and
interfaces and leads to excess run-time checking.
# Using a universal base class implies cost: Objects must be
heap-allocated to be polymorphic; that implies memory and access cost.
Heap objects don't naturally support copy semantics. Heap objects don't
support simple scoped behavior (which complicates resource management).
A universal base class encourages use of dynamic_cast and other
run-time checking.
>
these issues are right, but what is the alternative if we really need a
generic container?
boost::any, of course. :-) See the previous posts in this thread.

Cheers! --M

  #16  
Old August 15th, 2006, 05:55 PM
Diego Martins
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...


mlimber wrote:
Quote:
Diego Martins wrote:
Quote:
mlimber wrote:
Quote:
Diego Martins wrote:
If you like the Java style, create an Object class and make subclasses
that will behave like wrappers of built-in data types (Integer, Bool,
etc.)
>
This is generally frowned upon. See the reasons why here:
>
http://www.research.att.com/~bs/bs_faq2.html#object
>
and
>
http://www.artima.com/intv/goldilocks2.html
>
personally, I dislike this java-style. I only presented a possible
working solution for a "generic" container

# A "universal" class encourages sloppy thinking about types and
interfaces and leads to excess run-time checking.
# Using a universal base class implies cost: Objects must be
heap-allocated to be polymorphic; that implies memory and access cost.
Heap objects don't naturally support copy semantics. Heap objects don't
support simple scoped behavior (which complicates resource management).
A universal base class encourages use of dynamic_cast and other
run-time checking.

these issues are right, but what is the alternative if we really need a
generic container?
>
boost::any, of course. :-) See the previous posts in this thread.
>
Cheers! --M
sounds great! Can you explain to us how boost::any is implemented?

Diego Martins

  #17  
Old August 15th, 2006, 06:35 PM
mlimber
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...

Diego Martins wrote:
Quote:
sounds great! Can you explain to us how boost::any is implemented?
Not here. Ask on the Boost Developer (or User) list, or look through
the code.

Cheers! --M

  #18  
Old August 16th, 2006, 02:25 PM
Diego Martins
Guest
 
Posts: n/a
Default Re: map containing a string key and a templated value...


mlimber wrote:
Quote:
Diego Martins wrote:
Quote:
sounds great! Can you explain to us how boost::any is implemented?
>
Not here. Ask on the Boost Developer (or User) list, or look through
the code.
>
Cheers! --M
I can't figure out why some members of this great group take this
defensive posture.

Me and many users want to code in C++ and learn more C++ to write
better code in C++. This is the reason we spend time in usenet forums.

It is not bad to get a tool as a solution, but we must consider the
case when we aren't able to use external tools. Instead, many users do
prefer saying "BOOST AND GOOD BYE". This is not the first time I see
this things here :-(

This is not a helpdesk. This is a place where the users share their C++
experiencies. Why do ruin that?

Go rest and think about that

Diego Martins
HP

 

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over network members.
Post your question now . . .
It's fast and it's free

Popular Articles