Actually I'm quite sure I've missed something trivial here, but I just can't find it.
Seemingly I cannot read from a const map&
I try -
#include <iostream>
-
#include <map>
-
using namespace std;
-
-
void show (
-
const // troubling-const
-
map<char, double>& myconstmap )
-
{
-
cout << "A->" << myconstmap['A'] << "\n";
-
}
-
-
int main ()
-
{
-
map<char, double> mymap;
-
mymap['A']=0.1;
-
}
-
-
If I remove the troubling const I'm able to access it but I don'r really feel like giving up on const
I'm thankful for any hint
J
12 5748
The const has nothing to do with it.
It's your use of operator[] in the the cout in line 9. That operator returns a reference to the map element. It's possible to change the map byusing this reference. Your const gets in the way of that and you get a compile error.
Either: a) don't use const or b) use const but don't use the map [] operator.
The const has nothing to do with it.
It's your use of operator[] in the the cout in line 9. That operator returns a reference to the map element. It's possible to change the map byusing this reference. Your const gets in the way of that and you get a compile error.
ok
Either: a) don't use const
mhh, I dont really feel like this is a solution, but rather a workaround which I dont feel comfortable with. The map is created in one spot and I want to hand it around and read it from multiple places without the possibility to change it.
or b) use const but don't use the map [] operator.
But as far as I can see the only other way to access the elements in the map then is the const_iterator which is not suitable for me - I rather would need some kind of random access.
Well, ok thanks for your answer.
Maybe map is just not the right thing here - I'll look for something else.
Thanks.
Why insist on map::operator[] ???
You can use map::find() instead. That will return the pair that has your key and value.
Otherwise, you can write a new map iof your own be deriving from map (bs sure map has a virtual destructor) and then write an operator[] in your map that returns a const value for the key rather than a const_iterator.
Please note, access in a map is not random, like an array. Access is based on a key and not and element number. The map::operator[] tries to make the map look like an array but it does return the value in a form that allows you to change it.
Why insist on map::operator[] ???
You can use map::find() instead. That will return the pair that has your key and value.
Because I dont want to do something in logarithmic time, when it should be done in constant time.
Otherwise, you can write a new map iof your own be deriving from map (bs sure map has a virtual destructor) and then write an operator[] in your map that returns a const value for the key rather than a const_iterator.
That sounds like a very interessting idea - I think I'll try that. Very interessting. I have never thought about deriving from some stl thing. mhh...
Please note, access in a map is not random, like an array. Access is based on a key and not and element number. The map::operator[] tries to make the map look like an array but it does return the value in a form that allows you to change it.
I don't get that. What I meant when I said random was that I can access an arbitrary element in constant time - independent of whether I'm allowed to change the element or not. And as I expect a map to be something like a hashtable and I know my keys will all be unique (Im not actually using char as indicated in my example but pointers to struct), I would expect [] to execute in constant time.
Although now that you made me think about it again I dont find any statement about execution time of [] in
http://www.cppreference.com/cppmap/map_operators.html
What I meant when I said random was that I can access an arbitrary element in constant time - independent of whether I'm allowed to change the element or not. And as I expect a map to be something like a hashtable and I know my keys will all be unique (Im not actually using char as indicated in my example but pointers to struct), I would expect [] to execute in constant time.
A map is a red-black binary tree. Access is not in constant time like an array.
All STL associative containers use red-black trees.
There is a hashmap but it is still non-standard.
A map is a red-black binary tree. Access is not in constant time like an array.
Ok, I see. So the execution times of both, operator[] and find() are logarithmic, right?
I think, I'm going to put the map into a wrapper that provides something like - TYPE& operator[]( const key_type& key );
-
const TYPE& operator[]( const key_type& key ) const;
Besides the satisfaction of my const-request this would allow me to change from map to whatever, maybe a hash table in the future.
Yes, you could change the implementation of the tree.
Generally, I advise to not expose your implementation for that very reason. All of these STL containers should be fronted by an access class of your design and with your interface methods.
Ditto for memory using new and delete. I always use a Create/Delete function and bury the allocation.
Errr, Im afraid Im back .... I tried to:
you can write a new map iof your own be deriving from map (bs sure map has a virtual destructor) and then write an operator[] in your map that returns a const value for the key rather than a const_iterator.
like this: -
#include <iostream>
-
#include <map>
-
using namespace std;
-
-
-
template < typename keytype, typename TYPE >
-
class cmap: public std::map<keytype, TYPE>
-
{
-
public:
-
virtual const TYPE& operator[](const keytype& k) const // this seems to keep me from accessing the non-const operator[]
-
//virtual const TYPE& get(const keytype& k) const
-
{
-
// get rid of const so we are able to call operator[]()
-
const cmap<keytype,TYPE>& const_cmap = *this;
-
const std::map<keytype,TYPE>& const_map = const_cmap;
-
std::map<keytype,TYPE>& nonconst_map = const_cast < std::map<keytype,TYPE>& > ( const_map );
-
// retrieve the element and return it as const&
-
return nonconst_map[k];
-
}
-
-
virtual ~cmap(){}
-
};
-
-
-
-
int main (){
-
-
cmap <char, double> mycmap;
-
mycmap['A'] = 0.2; // compile-error: "assignment of read-only location"
-
-
const cmap<char, double>& const_mycmap = mycmap;
-
cout << const_mycmap['A'] << "\n";
-
//cout << const_mycmap.get('A') << "\n";
-
}
This doesnt compile due to line 29, so seemingly I do have a const operator[] now, but the non-const operator[] is gone.
If I exchange line 15 with 16 and 37 with 38 it works, but well then there is still no const operator[]() const.
You have to write your own cmap::operator[]. One for non-const cmaps and one for const cmaps.
No amount casting is going to help you.
Here is my try. It compiles and links but I didn't test it. -
#include <iostream>
-
#include <map>
-
#include <exception>
-
using namespace std;
-
-
-
template < typename keytype, typename TYPE >
-
class cmap: public std::map<keytype, TYPE>
-
{
-
public:
-
TYPE& operator[](const keytype& k)
-
-
{
-
map::iterator theData = this->lower_bound(k);
-
if (theData == this->end())
-
{
-
exception obj("key not found");
-
throw obj;
-
-
-
}
-
return theData->second;
-
}
-
TYPE operator[](const keytype& k) const
-
-
{
-
map::const_iterator theData = this->lower_bound(k);
-
if (theData == this->end())
-
{
-
exception obj("key not found");
-
throw obj;
-
-
-
}
-
return theData->second;
-
}
-
virtual ~cmap(){}
-
};
-
-
-
-
int main (){
-
-
cmap <char, double> mycmap;
-
mycmap['A'] = 0.2; // compile-error: "assignment of read-only location"
-
-
const cmap<char, double>& const_mycmap = mycmap;
-
cout << const_mycmap['A'] << "\n";
-
//cout << const_mycmap.get('A') << "\n";
-
}
-
Lastly, the camp destructor does not need to be virtual unless you create a cmap and use it as a map* or map&. And if you do that, be sure the map destructor is virtual. If it's not, that the signal that map cannot be used polymorphically.
You have to write your own cmap::operator[]. One for non-const cmaps and one for const cmaps.
ok, I had never guessed that!
And - ok, learned something again - obviously it is not possible to return a const TYPE& if there is no such object. which finally is the answer to my unspelled question "why is the const TYPE& operator[]() const not already implemented in std::map?". But the exception is a nice resolution to this. I think it suits my needs quite well, since if my code ever tries to call const_mycmap[key] for some undefined key, it is a bug anyways and I'll be thankful for the exception.
But contrary to your proposal, I don't want an exception in the case of accessing an undefined key in the non-const context. E.g. line 45 of your code raises an exception. Also it changes the semantics of the base class std::map in a surprising way.
Additionally, I needed to change the declaration of the iterators and replace the exception object. But this might be subject to different compilers.
Below is the version that works for me and with which I feel quite satisfied. -
#include <iostream>
-
#include <map>
-
#include <exception>
-
using namespace std;
-
-
-
class message: public exception
-
{
-
protected:
-
string What;
-
public:
-
message( string m ): What(m) {}
-
~message() throw() {}
-
virtual const char* what() const throw() {
-
return What.c_str();
-
}
-
};
-
-
-
-
template < typename keytype, typename TYPE >
-
class cmap: public std::map<keytype, TYPE>
-
{
-
public:
-
-
TYPE& operator[](const keytype& k)
-
{
-
// use the operator[] of the base class map
-
return map<keytype,TYPE>::operator[](k);
-
}
-
-
-
const TYPE& operator[](const keytype& k) const
-
{
-
//map::const_iterator theData ; // g++ says:
-
// `template<class _Key, class _Tp, class _Compare, class _Alloc>
-
// class std::map' used without template parameters
-
// missing template arguments before "theData"
-
-
typename map< keytype, TYPE >::const_iterator theData ;
-
// took me a while to figure out that (for whatever reason) typename
-
// is required here
-
-
theData = this->lower_bound(k);
-
if ( theData == this->end() )
-
{
-
//exception obj("key not found"); // g++ says:
-
// no matching function for call to
-
// `std::exception::exception(const char[14])'
-
-
message obj("key not found");
-
throw obj;
-
}
-
return theData->second;
-
}
-
-
virtual ~cmap(){}
-
};
-
-
-
-
int main ()
-
{
-
-
try
-
{
-
cmap <char, double> mycmap;
-
mycmap['A'] = 0.2;
-
cout << mycmap['A'] << " {" << &(mycmap['A']) << "}\n";
-
-
const cmap<char, double>& const_mycmap = mycmap;
-
cout << const_mycmap['A'] << " {" << &(const_mycmap['A']) << "}\n";
-
cout << const_mycmap['B'] << "\n"; // raises an exception, which is good!
-
}
-
catch ( message e )
-
{
-
cout << "Exception: \"" << e.what() << "\"\n";
-
exit( EXIT_FAILURE );
-
}
-
}
-
bugfix: it should be
theData = this->find(k);
instead of
theData = this->lower_bound(k);
Sign in to post your reply or Sign up for a free account.
Similar topics
by: Mark Van Orman |
last post by:
Hi all,
I have an application that logs in xml.
Assume <xmlLog></xmlLog>. In this element the app logs anything it gets
from foreign hosts. Now if the host sends xml data, the structure of the...
|
by: Evgeny |
last post by:
Hi, all!
I try to convert my existing code written in VC6 to VC7 and have some
problem with stl auto pointer template.
class CColumn;
#include <memory>
typedef auto_ptr<CMyBase> CMyBasePtr;
...
|
by: scottyman |
last post by:
I can't make this script work properly. I've gone as far as I can with
it and the rest is out of my ability. I can do some html editing but
I'm lost in the Java world. The script at the bottom of...
|
by: asclearuc |
last post by:
Hello
Is it possible to use map<string&, string&>?
Why I need it. I have a large amount of data obtained from XML file.
I should do processing of this data.
The processing takes many...
|
by: markoj |
last post by:
hi
i HAVE WRITTEN A perl script that will search a file and print output I have created a simple html doc i want to be able to click a link and it will print the output in of a specific file so i...
|
by: subramanian100in |
last post by:
consider the following program:
#include <cstdlib>
#include <iostream>
#include <map>
#include <utility>
#include <string>
using namespace std;
|
by: TrevRex |
last post by:
Hello,
I work for a non-profit in San Diego as a GIS Specialist. I have had to teach myself about some scripting to create some dynamic maps, but I am still very limited in my skills, so I have...
|
by: Rina0 |
last post by:
Cybersecurity engineering is a specialized field that focuses on the design, development, and implementation of systems, processes, and technologies that protect against cyber threats and...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM)
The start time is equivalent to 19:00 (7PM) in Central...
|
by: erikbower65 |
last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps:
1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal.
2. Connect to...
|
by: Taofi |
last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same
This are my field names
ID, Budgeted, Actual, Status and Differences
...
|
by: DJRhino1175 |
last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this -
If...
|
by: Rina0 |
last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
|
by: DJRhino |
last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer)
If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _
310030356 Or 310030359 Or 310030362 Or...
|
by: Mushico |
last post by:
How to calculate date of retirement from date of birth
|
by: DJRhino |
last post by:
Was curious if anyone else was having this same issue or not....
I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
| |