By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,652 Members | 1,842 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,652 IT Pros & Developers. It's quick & easy.

std::map associative container question

P: n/a
Hello everyone,

I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:

typedef std::map<string,doubleMap;

but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?
Maybe with a typename?

Thank you all,

a^2

Sep 21 '06 #1
Share this Question
Share on Google+
21 Replies


P: n/a
aaragon wrote:

I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:

typedef std::map<string,doubleMap;

but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?
Maybe with a typename?
Take a look at boost::any. If that's no help, you may need to describe
a bit more what it is you are trying to do. By the way, although I can
see good reasons not to use doubles, why do you care about wasting
storage? Is the map really that big?

Best regards,

Tom

Sep 21 '06 #2

P: n/a

Thomas Tutone wrote:
aaragon wrote:

I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:

typedef std::map<string,doubleMap;

but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?
Maybe with a typename?

Take a look at boost::any. If that's no help, you may need to describe
a bit more what it is you are trying to do. By the way, although I can
see good reasons not to use doubles, why do you care about wasting
storage? Is the map really that big?

Best regards,

Tom
Well, it's not that the map is big, but also when you request the key,
then the value is returned. Therefore, sometimes I'm expecting a bool
but instead I'm receiving a double (and I don't want to convert the
values nor put a specifier in front as (bool) for example). I was
wondering that maybe there is a templetized way to do this. For
example,

template<typename T>
....
typedef std::map<string,TMap;

but I don't think it may work.....

Sep 21 '06 #3

P: n/a
aaragon wrote:
Thomas Tutone wrote:
aaragon wrote:

I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:
>
typedef std::map<string,doubleMap;
>
but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?
Maybe with a typename?
Take a look at boost::any. If that's no help, you may need to describe
a bit more what it is you are trying to do. By the way, although I can
see good reasons not to use doubles, why do you care about wasting
storage? Is the map really that big?

Best regards,

Tom

Well, it's not that the map is big, but also when you request the key,
then the value is returned. Therefore, sometimes I'm expecting a bool
but instead I'm receiving a double (and I don't want to convert the
values nor put a specifier in front as (bool) for example). I was
wondering that maybe there is a templetized way to do this. For
example,

template<typename T>
...
typedef std::map<string,TMap;

but I don't think it may work.....
No, that definitely won't work. C++ is a strongly typed language, and
you need to instantiate the map using a particular type. As I said,
look at boost::any (see www.boost.org). Or maybe you can just do
something like the following:

struct Aaragon_multi_type {
int i;
double d;
bool b;
};

std::map<std::string, Aaragon_multi_type map;

Not space efficient, but would let store value of any of those in the
map...

Again, if you don't tell us what it is you want to do - i.e., why do
you want to store different types? - it's awfully hard to provide
useful advice.

Best regards,

Tom

Sep 21 '06 #4

P: n/a
aaragon wrote:
Hello everyone,

I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:

typedef std::map<string,doubleMap;

but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?
The short answer is: no. The long answer is: yes, but the overhead incurred
be the logic needed to arrange for one object to represent values from
possible different types is very likely going to null and void all possible
gains in storage consumption.

E.g., you could do something like:

struct number {
~number();
};

struct number_double : public base {
double value;
};

struct number_int : public base {
int value;
};

....

std::map<string,number*Map;

Then you have the overhead of one pointer per object and a real hassle to
sort out which object has which type (using dynamic_cast or some such
thing). In order for that to work, number needs to be polymorphic, which
usually means you have a vtable pointer. Given that heap allocation occurs
in chunks determined by the algorithm for new, we might already look at 20
to 36 bytes per entry in the map.

Have you verified that you really cannot afford the memory overhead from
converting everything to double, or are you engaging in premature
optimization?
Best

Kai-Uwe Bux
Sep 21 '06 #5

P: n/a
Kai-Uwe Bux wrote:
aaragon wrote:
Hello everyone,

I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:

typedef std::map<string,doubleMap;

but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?

The short answer is: no. The long answer is: yes, but the overhead incurred
be the logic needed to arrange for one object to represent values from
possible different types is very likely going to null and void all possible
gains in storage consumption.

E.g., you could do something like:

struct number {
~number();
};

struct number_double : public base {
double value;
};

struct number_int : public base {
int value;
};

...

std::map<string,number*Map;

Then you have the overhead of one pointer per object and a real hassle to
sort out which object has which type (using dynamic_cast or some such
thing). In order for that to work, number needs to be polymorphic, which
usually means you have a vtable pointer. Given that heap allocation occurs
in chunks determined by the algorithm for new, we might already look at 20
to 36 bytes per entry in the map.

Have you verified that you really cannot afford the memory overhead from
converting everything to double, or are you engaging in premature
optimization?
Best

Kai-Uwe Bux
Yes, I'm trying to write the code as optimal as possible from the
beginning. It is not that I have a big map. I'm trying to build a
genetic algorithm library so I decided to store all the possible
variables of the problem in a map. These variables include from
population size (an unsigned int) to probabilities of crossover and
mutation (double variables), or even boolean types (to see if a random
seed was given). I thought it would be cool to have everything in an
associative container so when I type map[popSize] then I get the
population size of the problem. However, as you can see the types are
different. What I'm doing right now is
typedef std::map<string,doubleMap;
so when I need an unsigned int for example, I put an identifier in
front (size_t)Map[popSize]. This works but I thought it was a better
way to do this.
I never thought that having a map for different types was as
complicated as this. Thank you guys for your help.

Sep 21 '06 #6

P: n/a
Thomas Tutone wrote:
aaragon wrote:
Thomas Tutone wrote:
aaragon wrote:
>
>
I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:

typedef std::map<string,doubleMap;

but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?
Maybe with a typename?
>
Take a look at boost::any. If that's no help, you may need to describe
a bit more what it is you are trying to do. By the way, although I can
see good reasons not to use doubles, why do you care about wasting
storage? Is the map really that big?
>
Best regards,
>
Tom
Well, it's not that the map is big, but also when you request the key,
then the value is returned. Therefore, sometimes I'm expecting a bool
but instead I'm receiving a double (and I don't want to convert the
values nor put a specifier in front as (bool) for example). I was
wondering that maybe there is a templetized way to do this. For
example,

template<typename T>
...
typedef std::map<string,TMap;

but I don't think it may work.....

No, that definitely won't work. C++ is a strongly typed language, and
you need to instantiate the map using a particular type. As I said,
look at boost::any (see www.boost.org). Or maybe you can just do
something like the following:

struct Aaragon_multi_type {
int i;
double d;
bool b;
};

std::map<std::string, Aaragon_multi_type map;

Not space efficient, but would let store value of any of those in the
map...
What if you used union instead of struct? That would be more space
efficient.
Again, if you don't tell us what it is you want to do - i.e., why do
you want to store different types? - it's awfully hard to provide
useful advice.

Best regards,

Tom
Sep 21 '06 #7

P: n/a
"aaragon" <al**************@gmail.comwrites:
typedef std::map<string,doubleMap;
so when I need an unsigned int for example, I put an identifier in
front (size_t)Map[popSize]. This works but I thought it was a better
way to do this.
Is there a reason why you can't use different maps? I can think of
cases where you can't, or don't want to, but I suspect that you
actually should better do.

Frankly, I think that the language making it hard for you to follow
your approach is a sign that you're trying to do the wrong thing.

You want to store a variable popSize as a value of a map. Is there a
reason why you can't use a proper variable: size_t popSize? Do you
have an arbitrary number of those? How are they used?

If you could post some code of what you're really trying to do, this
would help a lot.
I never thought that having a map for different types was as
complicated as this.
It's simple with boost::any, and for double, int and bool alone a
union is also a possibility. However, this is most certainly not want
you want to do.
Yes, I'm trying to write the code as optimal as possible from the
beginning. It is not that I have a big map.
You know that early optimisation is the source of all evil, do you?
But that's a different matter.

Jens
Sep 21 '06 #8

P: n/a

Jens Theisen wrote:
"aaragon" <al**************@gmail.comwrites:
typedef std::map<string,doubleMap;
so when I need an unsigned int for example, I put an identifier in
front (size_t)Map[popSize]. This works but I thought it was a better
way to do this.

Is there a reason why you can't use different maps? I can think of
cases where you can't, or don't want to, but I suspect that you
actually should better do.
Well, the only reason was to refer to all the parameters of the problem
with a single map. I did think about the possibility to having
different maps to hold different variable types but then I thought that
maybe there was a better way to do it.
Frankly, I think that the language making it hard for you to follow
your approach is a sign that you're trying to do the wrong thing.

You want to store a variable popSize as a value of a map. Is there a
reason why you can't use a proper variable: size_t popSize? Do you
have an arbitrary number of those? How are they used?
I didn't want to store the variables in the proper way, because I think
that at some stage of the code I will be accesing the same variables
from different locations (and different objects will be accesing these
variables as well). Also, there are some variables that do not belong
to any single object.
If you could post some code of what you're really trying to do, this
would help a lot.
I never thought that having a map for different types was as
complicated as this.

It's simple with boost::any, and for double, int and bool alone a
union is also a possibility. However, this is most certainly not want
you want to do.
I'll try this boost::any =)
>
Yes, I'm trying to write the code as optimal as possible from the
beginning. It is not that I have a big map.

You know that early optimisation is the source of all evil, do you?
But that's a different matter.
I didn't know this... why???????
Jens
Sep 21 '06 #9

P: n/a
"aaragon" <al**************@gmail.comwrites:
Well, the only reason was to refer to all the parameters of the problem
with a single map. I did think about the possibility to having
different maps to hold different variable types but then I thought that
maybe there was a better way to do it.
Do you have experience with dynamically typed languages such as Perl
or Python? In those, you do exactly what you're trying to do in C++.

You might not want to heed this advice, but I urge you: Let the type
system be your friend; don't use boost::any unless absolutely
necessary and rather use multiple maps, or even better, simple
variables as long as that's sufficient.

Don't cast around, especially not with C-style casts ( as in
(int)myvar ).

The type system is a feature of C++, not a nuisance. It pulls the
logic of your program together so that it doesn't fall apart.
Also, there are some variables that do not belong
to any single object.
Because there are global? Make them either global then, or have some
object that contains what's effectively global storage. Refactor it
when it gets too big.
I'll try this boost::any =)
Resist! :)
You know that early optimisation is the source of all evil, do you?
But that's a different matter.

I didn't know this... why???????
Because

1. you will not be successful (you don't know what will make your
program slow when it will eventually be)

but

2. you will waste resources in the try and probably also compromise
other design goals such as correctness.

I know that it's difficult not to early optimisation, but I'm
convinced it's wise.

Regards,

Jens
Sep 21 '06 #10

P: n/a
aaragon wrote:
Yes, I'm trying to write the code as optimal as possible from the
beginning. It is not that I have a big map. I'm trying to build a
genetic algorithm library so I decided to store all the possible
variables of the problem in a map. These variables include from
population size (an unsigned int) to probabilities of crossover and
mutation (double variables), or even boolean types (to see if a random
I think that to store the variables in a map, and then searching for them at
runtime, will be a lot slower that using member variables and let the
compiler do the job a compile time. What are you trying to optimize?

--
Salu2
Sep 21 '06 #11

P: n/a

Jens Theisen wrote:
"aaragon" <al**************@gmail.comwrites:
Well, the only reason was to refer to all the parameters of the problem
with a single map. I did think about the possibility to having
different maps to hold different variable types but then I thought that
maybe there was a better way to do it.

Do you have experience with dynamically typed languages such as Perl
or Python? In those, you do exactly what you're trying to do in C++.

You might not want to heed this advice, but I urge you: Let the type
system be your friend; don't use boost::any unless absolutely
necessary and rather use multiple maps, or even better, simple
variables as long as that's sufficient.

Don't cast around, especially not with C-style casts ( as in
(int)myvar ).
What is wrong with doing C casts? what could go wrong?
>
The type system is a feature of C++, not a nuisance. It pulls the
logic of your program together so that it doesn't fall apart.
Also, there are some variables that do not belong
to any single object.

Because there are global? Make them either global then, or have some
object that contains what's effectively global storage. Refactor it
when it gets too big.
I thought that working without global variables is a must in C++.
>
I'll try this boost::any =)

Resist! :)
You know that early optimisation is the source of all evil, do you?
But that's a different matter.
>
I didn't know this... why???????

Because

1. you will not be successful (you don't know what will make your
program slow when it will eventually be)

but

2. you will waste resources in the try and probably also compromise
other design goals such as correctness.

I know that it's difficult not to early optimisation, but I'm
convinced it's wise.

Regards,

Jens
Thanks for the tips Jens. I'll follow your advise. I'll use private
member variables to store the variables.

Sep 21 '06 #12

P: n/a

Julián Albo wrote:
aaragon wrote:
Yes, I'm trying to write the code as optimal as possible from the
beginning. It is not that I have a big map. I'm trying to build a
genetic algorithm library so I decided to store all the possible
variables of the problem in a map. These variables include from
population size (an unsigned int) to probabilities of crossover and
mutation (double variables), or even boolean types (to see if a random

I think that to store the variables in a map, and then searching for themat
runtime, will be a lot slower that using member variables and let the
compiler do the job a compile time. What are you trying to optimize?

--
Salu2
I'm writing a code to optimize 2D and 3D networks with genetic
algorithms.

Sep 21 '06 #13

P: n/a

jo***********@gmail.com wrote:
Thomas Tutone wrote:
aaragon wrote:
Thomas Tutone wrote:
aaragon wrote:


I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:
>
typedef std::map<string,doubleMap;
>
but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?
Maybe with a typename?

Take a look at boost::any. If that's no help, you may need to describe
a bit more what it is you are trying to do. By the way, although I can
see good reasons not to use doubles, why do you care about wasting
storage? Is the map really that big?

Best regards,

Tom
>
Well, it's not that the map is big, but also when you request the key,
then the value is returned. Therefore, sometimes I'm expecting a bool
but instead I'm receiving a double (and I don't want to convert the
values nor put a specifier in front as (bool) for example). I was
wondering that maybe there is a templetized way to do this. For
example,
>
template<typename T>
...
typedef std::map<string,TMap;
>
but I don't think it may work.....
No, that definitely won't work. C++ is a strongly typed language, and
you need to instantiate the map using a particular type. As I said,
look at boost::any (see www.boost.org). Or maybe you can just do
something like the following:

struct Aaragon_multi_type {
int i;
double d;
bool b;
};

std::map<std::string, Aaragon_multi_type map;

Not space efficient, but would let store value of any of those in the
map...

What if you used union instead of struct? That would be more space
efficient.
What is a union??? some standard library container???
>
Again, if you don't tell us what it is you want to do - i.e., why do
you want to store different types? - it's awfully hard to provide
useful advice.

Best regards,

Tom
Sep 21 '06 #14

P: n/a
aaragon schrieb:
Jens Theisen wrote:
>It's simple with boost::any, and for double, int and bool alone a
union is also a possibility. However, this is most certainly not want
you want to do.

I'll try this boost::any =)
I would suggest using boost::variant instead of boost::any, because I found
it more usefull, and maybe faster.

boost::variant stores, just like boost::any, one value but of a specific
set of types, just like a union, but in a typesafe way.

Unlike boost::any, you can use a generic visitor pattern for
boost::variant, what makes it more usefull, since you don't have to go with
switch() or if()/else() constructs for every type that could be stored.

Just read the documentation of both at the boost website and compare.

--
Thomas
http://www.netmeister.org/news/learn2quote.html
Sep 22 '06 #15

P: n/a

Thomas J. Gritzan wrote:
aaragon schrieb:
Jens Theisen wrote:
It's simple with boost::any, and for double, int and bool alone a
union is also a possibility. However, this is most certainly not want
you want to do.
I'll try this boost::any =)

I would suggest using boost::variant instead of boost::any, because I found
it more usefull, and maybe faster.

boost::variant stores, just like boost::any, one value but of a specific
set of types, just like a union, but in a typesafe way.

Unlike boost::any, you can use a generic visitor pattern for
boost::variant, what makes it more usefull, since you don't have to go with
switch() or if()/else() constructs for every type that could be stored.

Just read the documentation of both at the boost website and compare.

--
Thomas
http://www.netmeister.org/news/learn2quote.html
I'll take a look... thank you Thomas...

Sep 22 '06 #16

P: n/a
"aaragon" <al**************@gmail.comwrites:
What is wrong with doing C casts? what could go wrong?
This advice is not as important as the other, though. C-style casts do
allow too much, as in

struct A { };
struct B : A { };
struct C : A { };

int main()
{
B * ptr = new B;
C * ptr2 = ( C* )(ptr);
}

which static_cast would no allow. Also, when using static_cast and
const_cast, constness is separated from the other kinds of casted
leading to a cleaner style.

However, I admit that this is not a particularly strong argument. Does
anyone have a more compelling example of what frequently goes wrong
with C-style casts?
I thought that working without global variables is a must in C++.
Clearly global storage is undesirable, but there are always tradeoffs
and there are more important things to get right. Important is that
your globabl variables are all conceptually constant. For example, a
global cache for something might be okay, as the caches presence
should be transparant to the rest of the logic - the program should
behave as there was no cache.

I you post some code after you played around a little bit, I'm sure
you'll get a free code review here. :)

Regards,

Jens

Sep 22 '06 #17

P: n/a

Jens Theisen wrote:
"aaragon" <al**************@gmail.comwrites:
What is wrong with doing C casts? what could go wrong?

This advice is not as important as the other, though. C-style casts do
allow too much, as in

struct A { };
struct B : A { };
struct C : A { };

int main()
{
B * ptr = new B;
C * ptr2 = ( C* )(ptr);
}

which static_cast would no allow. Also, when using static_cast and
const_cast, constness is separated from the other kinds of casted
leading to a cleaner style.

However, I admit that this is not a particularly strong argument. Does
anyone have a more compelling example of what frequently goes wrong
with C-style casts?
I thought that working without global variables is a must in C++.

Clearly global storage is undesirable, but there are always tradeoffs
and there are more important things to get right. Important is that
your globabl variables are all conceptually constant. For example, a
global cache for something might be okay, as the caches presence
should be transparant to the rest of the logic - the program should
behave as there was no cache.

I you post some code after you played around a little bit, I'm sure
you'll get a free code review here. :)

Regards,

Jens
Thanks Jens! I appreciate it... =)

Sep 22 '06 #18

P: n/a

Kai-Uwe Bux wrote:
aaragon wrote:
Hello everyone,

I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:

typedef std::map<string,doubleMap;

but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?

The short answer is: no. The long answer is: yes, but the overhead incurred
be the logic needed to arrange for one object to represent values from
possible different types is very likely going to null and void all possible
gains in storage consumption.

E.g., you could do something like:

struct number {
~number();
};
virtual ~number(); , instead
struct number_double : public base {
double value;
};

struct number_int : public base {
int value;
};
public number, instead of public base
...

std::map<string,number*Map;
Kai, don't get me wrong. Actually, I know it was only typos, but my
intention is help the OP.

Diego Martins
HP

Sep 22 '06 #19

P: n/a
Diego Martins wrote:
Kai-Uwe Bux wrote:
>aaragon wrote:
>>Hello everyone,
...

Kai, don't get me wrong. Actually, I know it was only typos, but my
intention is help the OP.
The name you should have used is "Kai-Uwe", not "Kai". Don't get me
wrong, Diego.
Sep 22 '06 #20

P: n/a
Diego Martins wrote:
>
Kai-Uwe Bux wrote:
>aaragon wrote:
Hello everyone,

I would like to know if there is a way to use the std::map to store
different types for one of its two types. That is, I'm trying to use
it as:

typedef std::map<string,doubleMap;

but instead of double, I have integers, even booleans so I guess that
the use of double waste a lot of storage. Is there any way to do this?

The short answer is: no. The long answer is: yes, but the overhead
incurred be the logic needed to arrange for one object to represent
values from possible different types is very likely going to null and
void all possible gains in storage consumption.

E.g., you could do something like:

struct number {
~number();
};

virtual ~number(); , instead
>struct number_double : public base {
double value;
};

struct number_int : public base {
int value;
};

public number, instead of public base
>...

std::map<string,number*Map;
Oops, thanks for the corrections.
Kai, don't get me wrong.
Let me make one of my own: it's "Kai-Uwe".
Actually, I know it was only typos, but my intention is help the OP.
That's always understood. To tell the truth, "base" was a typo. The
missing "virtual" was a real misthink: I had the virtual in there at some
point and deleted it thinking I could do without. Don't ask why or what I
was thinking -- it's beyond me now, especially since I went on to write
that number has to be polymorphic.
Thanks again

Kai-Uwe Bux
Sep 22 '06 #21

P: n/a

Victor Bazarov wrote:
Diego Martins wrote:
Kai-Uwe Bux wrote:
aaragon wrote:

Hello everyone,

...
Kai, don't get me wrong. Actually, I know it was only typos, but my
intention is help the OP.

The name you should have used is "Kai-Uwe", not "Kai". Don't get me
wrong, Diego.
Sorry about that. :(

Oct 17 '06 #22

This discussion thread is closed

Replies have been disabled for this discussion.