473,383 Members | 1,788 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,383 software developers and data experts.

maps that don't insert default items

I would like to use maps as a container type, but I don't like how the
[] operator returns a default value. Is there a way to make [] return
NULL if it can't find the value?

I know I can do this:

typedef numMap map<int,myClass*>;
numMap nums;

if( nums.find(99) != nums.end() )
{
cout << "nums[99] is: " << nums[99] << endl;
}

I don't know how efficient this is, as it looks up the key 99 twice. To
avoid this situation:

numMap::iterator itr = nums.find(99);
if( itr != nums.end() )
{
cout << "nums[99] is: " << *nums << endl;
}

I don't find all this very convenient. Perhaps I am just complaining
too much.

~S

Jul 19 '05 #1
6 2909
"shea martin" <sa******@telus.net> wrote...
I would like to use maps as a container type, but I don't like how the
[] operator returns a default value. Is there a way to make [] return
NULL if it can't find the value?
Don't use operator[].
I know I can do this:

typedef numMap map<int,myClass*>;
numMap nums;

if( nums.find(99) != nums.end() )
{
cout << "nums[99] is: " << nums[99] << endl;
}

I don't know how efficient this is, as it looks up the key 99 twice. To
avoid this situation:

numMap::iterator itr = nums.find(99);
if( itr != nums.end() )
{
cout << "nums[99] is: " << *nums << endl;
}

I don't find all this very convenient. Perhaps I am just complaining
too much.


Yep.

Victor
Jul 19 '05 #2
shea martin <sa******@telus.net> wrote in message news:<3F**************@telus.net>...
I would like to use maps as a container type, but I don't like how the
[] operator returns a default value. Is there a way to make [] return
NULL if it can't find the value?
First, the default value for a pointer is NULL, so it *does* return
NULL if it can't find the value. However, you might be concerned that
operator[] inserts the element if it wasn't already present, and also
that, because of this, it can't be used on const maps.
I know I can do this:

typedef numMap map<int,myClass*>;
numMap nums;

if( nums.find(99) != nums.end() )
{
cout << "nums[99] is: " << nums[99] << endl;
}

I don't know how efficient this is, as it looks up the key 99 twice.
Yes, it is, isn't it...
To avoid this situation:

numMap::iterator itr = nums.find(99);
if( itr != nums.end() )
{
cout << "nums[99] is: " << *nums << endl;
}
That's how it is intended to be used.
I don't find all this very convenient. Perhaps I am just complaining
too much.


Sounds like it. However, don't forget that C++ actually allows you to
write your own functions:

template <typename K, typename V, typename P, typename A>
V *find (std::map<K, V *, P, A> &m, const K &key) {
typename std::map<K, V *, P, A>::iterator i = m.find(key);
return (i != m.end()) ? i->second : 0;
}

template <typename K, typename V, typename P, typename A>
const V *find (const std::map<K, V *, P, A> &m, const K &key) {
typename std::map<K, V *, P, A>::const_iterator i = m.find(key);
return (i != m.end()) ? i->second : 0;
}

class myClass;

int main () {
typedef std::map<int, myClass *> numMap;
numMap nums;

if (myClass *obj = find(nums, 99)) {
std::cout << "nums[99] is: " << obj << std::endl;
}
}

- Shane
Jul 19 '05 #3
shea martin <sa******@telus.net> wrote in message news:<3F**************@telus.net>...
I would like to use maps as a container type, but I don't like how the
[] operator returns a default value. Is there a way to make [] return
NULL if it can't find the value?
Blah, it's annoying behavior in certain situations I'll agree, but
there's no good way for it to be implemented as you (and I) desire.
Returning null works if the map value is a pointer (and in fact this
is what happens, though it still adds a null pointer to the map which
is probably not what you want), but not otherwise. There are three
alternatives:

1. Raise an exception,
2. Use something like the boost::optional,
3. Act like set and return a pair with the second value a bool to
indicate if it was in the map.

The first option would rarely be ideal, as exceptions are somewhat
costly at runtime and such an error would usually not be of a nature
that would merit their use.

The second and third options are very close to the same solution, but
both destroy the niceness of the [] syntax.

Besides, doing so would then make it impossible to insert values into
the map using [], so you can only have it one way.

I know I can do this:

typedef numMap map<int,myClass*>;
numMap nums;

if( nums.find(99) != nums.end() )
{
cout << "nums[99] is: " << nums[99] << endl;
}

I don't know how efficient this is, as it looks up the key 99 twice. To
avoid this situation:

numMap::iterator itr = nums.find(99);
if( itr != nums.end() )
{
cout << "nums[99] is: " << *nums << endl;
}

I don't find all this very convenient. Perhaps I am just complaining
too much.

~S

Jul 19 '05 #4
sb******@cs.uic.edu (Shane Beasley) wrote in message news:<2f**************************@posting.google. com>...
shea martin <sa******@telus.net> wrote in message news:<3F**************@telus.net>... template <typename K, typename V, typename P, typename A>
V *find (std::map<K, V *, P, A> &m, const K &key) {
typename std::map<K, V *, P, A>::iterator i = m.find(key);
return (i != m.end()) ? i->second : 0;
}


This is non-portable, as std::map may have extra
implementation-defined arguments. You'd need something like

template < typename MAP, typename pV = typename MAP::value_type >
pV find ( MAP &m, typename MAP::key_type const& key )

( nested types could be wrong, but you get the idea )

Regards,
--
Michiel Salters
Jul 19 '05 #5
<snip>

In "The C++ Programming Language" Third edition on page 374 he says:
"Exception handling is a less structured mechanism than local control
structures such as if and for and is *often les efficient* when an
exception is actually thrown."
Looks like it is costly at run time, though I guess the cost is
implementation specific.
He is saying that a thrown exception may be somewhat less efficient than an
if/then/else! If it's even in the ballpark, that's still pretty efficient.
However, to select a design for a relatively rare event like not finding
something you expect to find in a map, run time efficiency would be WAY down
my list of criteria. Maintainability would probably be first, as it usually
is.

Exceptions are a great feature of the C++ language, and refusing to use them
based on antecdotal evidence of run time inefficiency is unsound IMHO.

--
"Codito ergo sum"
Roel Schroeven


--
Cycho{HHR}
http://home.rochester.rr.com/cyhome/
Jul 19 '05 #6
"Evan" <ee****@psu.edu> wrote in message
news:3f**************************@posting.google.c om...
"Cy Edmunds" <ce******@spamless.rochester.rr.com> wrote in message

news:<I_*******************@twister.nyroc.rr.com>. ..
Costly at run time? What makes you think so? Stroustrop says they are so
efficient at runtime that it is tempting to just use them as control
structures. (But then he says not to anyway.)


Hmmmm, I've recently read somewhere that they are somewhat
inefficient. I can't remember where (in fact, the delay in responding
is partially to see if I would think of it) or I'd give you a
reference. It's possible that it was wrong as I too have heard of
exceptions used for control structures.

Still, that wasn't the main reason I decided that they were
inappropriate. The main reason was that which I wrote later:
Besides, doing so would then make it impossible to insert values into
the map using [], so you can only have it one way.


I thought that it might be possible to optionally install and
uninstall exception handlers for [], but dismissed it. However, I have
since read in Josuttis about the standard streams using a similar
approach to dealing with input errors, so maybe that could be an
optional extension for library makers (I'm not sure if it conflicts
with any of the standard, though I suspect it might with an exception
gurantee).

-Evan


OK, you have shamed me into getting around to publish some code which in
fact lets you do it "both ways". You can go with [] if that suits you but
use some functions which throw exceptions otherwise. Just look under
"throwmap" in the link in my sig.

--
Cy
http://home.rochester.rr.com/cyhome/
Jul 19 '05 #7

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

Similar topics

12
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. ...
2
by: maltchev | last post by:
i need to insert data from an xml file into sql server table. the xml file contains only one record. how to insert the data? how to map the names of the fields in the xml file and the table?...
3
by: Sean | last post by:
Have you ever wanted to add the great features inherent in Google Maps? Here is how you do it. ============== == STEP ONE == ============== Create a new MS Access form called frmGoogleMap....
5
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...
4
by: Anamika | last post by:
I want to create a map,which will be having string as a key and the related data as a structure... So can I use user defined data types as the data in maps? If so How I can use it... What is...
6
by: Hicham Mouline | last post by:
Hello, I am attempting to design a class: class C { std::map<double, const Ama; std::map<double, const Bma; ..
4
jlm699
by: jlm699 | last post by:
I've looked at the other articles about maps of maps and am still stuck on this! I'm trying to basically make an enumeration of a data monitoring app. Instead of displaying numbers for certain...
15
by: brad | last post by:
Do maps convert to multimaps if the same key is inserted more than once?
19
by: C++Liliput | last post by:
I have a custom String class that contains an embedded char* member. The copy constructor, assignment operator etc. are all correctly defined. I need to create a map of my string (say a class...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
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: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
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:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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.