473,382 Members | 1,329 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

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!

Aug 10 '06 #1
17 2184
de*******@hotmail.com schrieb:
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
Aug 10 '06 #2
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?

Aug 10 '06 #3

de*******@hotmail.com wrote:
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*>;

Aug 10 '06 #4
de*******@hotmail.com schrieb:
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
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
Aug 10 '06 #5
zh**********@gmail.com wrote:
de*******@hotmail.com wrote:
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)
[...]
>
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)

Aug 10 '06 #6
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...

Aug 10 '06 #7
de*******@hotmail.com wrote:
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

Aug 10 '06 #8
de*******@hotmail.com wrote:
[...] 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...
Aug 10 '06 #9
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:
de*******@hotmail.com wrote:
[...] 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...
Aug 10 '06 #10
de*******@hotmail.com wrote:
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

Aug 10 '06 #11
mlimber wrote:
de*******@hotmail.com wrote:
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...
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>
>(suckMap["lonely long") ) {
cout << t->data << "is a long value" << endl;
}

Hope this helps

Diego Martins

Aug 11 '06 #12
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
>
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>
(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

Aug 11 '06 #13

mlimber wrote:
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

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>
>(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

Aug 14 '06 #14
Diego Martins wrote:
mlimber wrote:
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

Aug 14 '06 #15

mlimber wrote:
Diego Martins wrote:
mlimber wrote:
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

Aug 15 '06 #16
Diego Martins wrote:
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

Aug 15 '06 #17

mlimber wrote:
Diego Martins wrote:
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

Aug 16 '06 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Thomas Matthews | last post by:
Hi, I'm working with Borland C++ Builder 6.2. My project uses the std::string class. However, Borland in its infinite wisdom has its own string class, AnsiString. To make my life easier, I...
9
by: Jon Wilson | last post by:
I have a class which needs to accumulate data. The way we get this data is by calling a member function which returns float on a number of different objects of different type (they are all the...
2
by: Alex Drummond | last post by:
Hello, Is there any way of specializing a templated function on a type which is itself templated? Here's the simplest example of the problem I can think of. Say I have written an implementation...
6
by: Dan Huantes | last post by:
I was presented a problem today where a class had member variable that was an object of a templated class. The class wanted to instantiate the object as a private member variable and call a...
0
by: John Crowley | last post by:
I keep running into this over and over again... I want a block server control that renders a header and footer, and child controls in between. But I don't want a templated control, for the...
6
by: Alex | last post by:
I have been loving the templated datacolumns of the datagrid. I have stumbled onto a problem though that is beyond by knowledge and I was hoping someone here could jumpstart me. My templated...
2
by: domehead100 | last post by:
I have a templated class, CDerived: template <typename TValue, typename TDraw, typename TEdit ...> class CDerived : public CBase { TValue m_Value public: TValue& GetValue() const {
14
by: Christopher | last post by:
Related to my last post, but seperate question Can a class be made into a container of its self? Could I Create an attribute class representing a name, value pair Create an attributeGroup...
2
card
by: card | last post by:
Hi everyone, I have a question about referencing a nested class contained within a templated class. Of course the best way to show you is by example. Here's my templated classes: #include...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

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.