|
Well, but it is possible to alter the value.. That's why you get a reference to the container<T>::value_type instead of an iterator. In the map case, the value_type is a pair consisting of the key and value.
--
You copy and paste yourself into my brain.
You always find your way back into my brain.
|
|
|
|
|
Thanks again for replying.
That being the case, I see little value in using the "for_each" algorithm when dealing with maps (perhaps with ANY container, since all the user is relegated to, is a set of "read only" type activities). You certainly seem to have more freedom in doing anything with ANY container by simply using the C++ "for" statement.
to the STL "for_each" algorithm.
William
Fortes in fide et opere!
|
|
|
|
|
What are you talking about? As Michael Dunn pointed out, you get a pair<const string,string>& as an argument to your functor. If you want to modify the value, just do arg.second = whatever_you_fancy .
for_each does not relegate the user to read only types.
struct addone {
void operator()(std::map<int, int>::value_type & arg) const {
arg.second++;
}
}; What is so read only with that?
You cannot modify the key at all since it may break the ordering restrictions of the associative container - this by design so that these containers can be implemented using hash tables or search trees. You cannot modify the container itself because it could invalidate iterators for the algorithms in ways that cannot be anticipated.
What you must have is an extra level of indirection because of the associativity rules - in this case the container itself. Since you are modifying order (keys) - not values - you need to handroll your own algorithm.
--
You copy and paste yourself into my brain.
You always find your way back into my brain.
|
|
|
|
|
Thanks for replying.
Prior to my response, I had done this.
void FnObj::operator() (const PAIR_KV& PA)
{
PAIR_KV PAIR = PA;
if(PAIR.first == "Old Key")
{
PAIR.second = "This is the NEW value for the old key";
}
} As you can see, I typed in a new string value to the old key second argument. When I ran the program and displayed its content, the new string value did not get shown. The old value was still in the map.
Unless I am absolutely not supposed to do ANYTHING inside the function object routine, this is what I'm talking about.
William
Fortes in fide et opere!
|
|
|
|
|
Of course nothing happened with the old values in your map. Look at what you're doing! You're accepting a PAIR_KV by const reference. You then assign it to a stack based PAIR_KV object. You get a copy! You are modifying the local copy on the stack.
Do this instead
typedef map<string, string> MapStr;
void FnObj::operator() (MapStr::value_type& PA) {
if(PA.first == "Old Key") {
PA.second = "This is the NEW value for the old key";
}
}
Why did you have a const string as key to begin with? Look, I seriously believe that you should get a good book on STL. I recommend Generic Programming and the STL: Using and Extending the C++ Standard Template Library by Matthew H. Austern, ISBN 0201309564.
--
You copy and paste yourself into my brain.
You always find your way back into my brain.
|
|
|
|
|
You are great on the giving of advice, but very poor on the testing of your own advice, because if you had tested the advice you were giving, you would have discovered they DON'T WORK. I know they don't work because I applied what you suggested and ended up (the latest) with 6 errors!!
Moreover, if you had looked closely, you would have seen that I had:
typedef pair<string, string> PAIR_KV; That's my "value_type" for the map that you keep talking about so much. It's there! SEE! It's there! I don't need your "MapStr::value_type&" suggestion, but I used it anyway just to see if it would work, ... and IT DIDN'T!! So much for your well-informed advice.
Yes, I had tried removing "const" from all the places they were being used and ended up with errors of one kind or another, and even tried using the reference straight from the parameter list of the function object "operator()" (without creating one on the stack). That didn't work either (meaning, it produced several errors)!
If you had done the various testings as I did, you would have found that "for_each" is just not a good algorithm for dealing with maps. It's obvious you didn't know that, based on the incorrect advice you have been giving.
NONE of the advice you have given so far worked. NONE! But there you are, telling me to go read up on certain STL books. FYI, I do my share of reading, and practicing with the STL almost every day. I certainly DON'T NEED another one of your gratuitous advice. KISS OFF!!
William
Fortes in fide et opere!
|
|
|
|
|
#include <map>
#include <iostream>
#include <utility>
#include <algorithm>
typedef std::map<int, int> IntMap;
struct addone {
void operator()(IntMap::value_type& v) const {
v.second++;
}
};
struct print {
void operator()(IntMap::value_type& v) const {
std::cout << "first = " << v.first << ", second = " << v.second << std::endl;
}
};
int main(int argc, char* argv[])
{
IntMap map;
map.insert(std::make_pair(1, 1));
map.insert(std::make_pair(2, 2));
map.insert(std::make_pair(3, 3));
map.insert(std::make_pair(4, 4));
map.insert(std::make_pair(5, 5));
std::for_each(map.begin(), map.end(), print());
std::for_each(map.begin(), map.end(), addone());
std::for_each(map.begin(), map.end(), print());
return 0;
} I'm just being honest; Do yourself a favor - stop whining and pick up an STL book.
--
You copy and paste yourself into my brain.
You always find your way back into my brain.
|
|
|
|
|
KISS OFF!!
Who needs your crappy little "int" addone sample?
I've had enough of your unworkable samples in the past. I don't need anymore.
If you didn't understand my last message, it states, "I do my share of reading just about everyday." I DON'T NEED you to tell me what to do.
Take your crappy little "map.insert" sample and SHOVE IT!!
It wouldn't hurt for you to do some reading of your own also. You clearly need it. All those unworkable advice you've been giving. You definitely need to do a lot of reading yourself.
William
Fortes in fide et opere!
|
|
|
|
|
At least you're entertaining.
--
You copy and paste yourself into my brain.
You always find your way back into my brain.
|
|
|
|
|
Even that you lack.
William
Fortes in fide et opere!
|
|
|
|
|
Oh, please guys, continue fighting. This is very funny
"semper aliquid haeret", Bacon.
-- Sebastián.
|
|
|
|
|
Hey, I'm not fighting.
--
You're entertaining at least.
|
|
|
|
|
The code example provided by Jörgen Sigvardsson was correctly updating a map of ints. It is easy to change this example to work with strings.
<br />
#include <map><br />
#include <iostream><br />
#include <utility><br />
#include <algorithm><br />
#include <string><br />
<br />
<br />
typedef std::map<std::string,std::string> StringMap;<br />
<br />
struct update<br />
{<br />
void operator() ( StringMap::value_type& v ) const<br />
{<br />
if ( v.first == "second" )<br />
v.second = "replaced value";<br />
}<br />
};<br />
<br />
struct print<br />
{<br />
void operator() ( StringMap::value_type& v ) const<br />
{<br />
std::cout << "first = " << v.first << ", second = " << v.second << std::endl;<br />
}<br />
};<br />
<br />
int main( int argc, char* argv[] )<br />
{<br />
StringMap testMap;<br />
<br />
testMap.insert( StringMap::value_type("first", "1") );<br />
testMap.insert( StringMap::value_type("second", "2") );<br />
testMap.insert( StringMap::value_type("third", "3") );<br />
testMap.insert( StringMap::value_type("fourth", "4") );<br />
testMap.insert( StringMap::value_type("fifth", "5") );<br />
<br />
std::for_each(testMap.begin(), testMap.end(), print());<br />
std::for_each(testMap.begin(), testMap.end(), update());<br />
std::for_each(testMap.begin(), testMap.end(), print());<br />
<br />
return 0;<br />
}<br />
However, as you know (from your comments in your original post), the code in the "update" functor is basically doing a find. However, since the for_each does a loop through all elements of the map, this is much less efficient than doing an actual find. If you need to do single updates to elements in a map which have particular key values, it would normally be better to just do the find and then update the element. The for_each algorithm is really only appropriate if you need to access every element in the container.
Best regards,
John
|
|
|
|
|
Thanks for replying.
Your sample does work.
William
Fortes in fide et opere!
|
|
|
|
|
jbarton wrote:
If you need to do single updates to elements in a map which have particular key values, it would normally be better to just do the find and then update the element.
That depends a little on how many values you are updating. If you are updating few elements, then the approach you mention is more efficient. But if the number of values are many, then an iteration is faster. Assuming that the map is implemented as a balanced search tree, you need to find out how O(k * log(n)) relates to O(n), where k is the number of values to update, and n is the number of elements in the map. Of course, if it's a hashmap, then the approach you mention is most likely faster for basically all k (unless, of course, the hash algorithm is very slow).
I guess it would be advantageous to encapsulate this algorithm into its own function, and let itself adapt to the problem size automatically. But hey, how would I know? I just post faulty samples and is a retard according to some.
--
You're entertaining at least.
|
|
|
|
|
I think the idea of iterating through the map to update multiple elements has merit. If (for instance) I want to update the data associated with all keys that match a particular pattern, there really isn't any way that I could do it without iterating through all elements in the map.
When I have a list of specific key values whose data I want to update, I find it difficult to set up a functor that efficiently checks for these key values and then updates the associated data values. It may be possible using another map or hash within the functor to lookup the key value and then get the replacement value. With only simple if / else if comparisons, I think that the overhead of the functor would probably remove any advantage gained by not using find on each key value.
Unless the program I was writing was running too slowly and by profiling I found it to be due to using find to update the map, I would probably stick with using find.
If you know of a better way of writing this functor, let me know. I am always interested in hearing other approaches.
Best regards,
John
|
|
|
|
|
Hello,
please tell me how to make a 2d and 3d vector using stl....and also how to assign and get values from it then.....i think i have made the 2d vector correctly but cant seem to assign values to it..THIS IS THE APPROACH I USED
typedef std::vector<int> sArray;
std::vector<sarray> m_map;
std::vector<int> v;
v.resize(m_no_horz_tiles,-1);
for (int i = 0 ; i < m_no_vert_tiles; i++)
{
m_map.push_back(v);
}
but the thing is i cant assign values to my 2d vector like this, given i and j
m_map[i][j] = 1; //value not stored don know why ?????
please guide me...
Thank you
|
|
|
|
|
Interesting.
Try initializing it via constructor.
std::vector v(m_no_horz_tiles, 0);
Kuphryn
|
|
|
|
|
Hello Omar,
I rewrote your code above as follows :
#include <vector>
#include <iostream.h>
#include <stdio.h>
typedef std::vector<int> sArray;
void main()
{
std::vector<sArray> m_map;
std::vector<int> v;
int i = 0, j = 0, m_no_horz_tiles = 5, m_no_vert_tiles = 10;
v.resize(m_no_vert_tiles, 0);
for (i = 0 ; i < m_no_horz_tiles; i++)
{
m_map.push_back(v);
}
for (i = 0 ; i < m_no_horz_tiles; i++)
{
for (j = 0 ; j < m_no_vert_tiles; j++)
{
m_map[i][j] = (i * 10) + j;
}
}
for (i = 0 ; i < m_no_horz_tiles; i++)
{
for (j = 0 ; j < m_no_vert_tiles; j++)
{
cout << "m_map[" << i << "][" << j << "] == " << m_map[i][j] << endl;
}
}
}
The above code yielded the following output :
m_map[0][0] == 0
m_map[0][1] == 1
m_map[0][2] == 2
m_map[0][3] == 3
m_map[0][4] == 4
m_map[0][5] == 5
m_map[0][6] == 6
m_map[0][7] == 7
m_map[0][8] == 8
m_map[0][9] == 9
m_map[1][0] == 10
m_map[1][1] == 11
m_map[1][2] == 12
m_map[1][3] == 13
m_map[1][4] == 14
m_map[1][5] == 15
m_map[1][6] == 16
m_map[1][7] == 17
m_map[1][8] == 18
m_map[1][9] == 19
m_map[2][0] == 20
m_map[2][1] == 21
m_map[2][2] == 22
m_map[2][3] == 23
m_map[2][4] == 24
m_map[2][5] == 25
m_map[2][6] == 26
m_map[2][7] == 27
m_map[2][8] == 28
m_map[2][9] == 29
m_map[3][0] == 30
m_map[3][1] == 31
m_map[3][2] == 32
m_map[3][3] == 33
m_map[3][4] == 34
m_map[3][5] == 35
m_map[3][6] == 36
m_map[3][7] == 37
m_map[3][8] == 38
m_map[3][9] == 39
m_map[4][0] == 40
m_map[4][1] == 41
m_map[4][2] == 42
m_map[4][3] == 43
m_map[4][4] == 44
m_map[4][5] == 45
m_map[4][6] == 46
m_map[4][7] == 47
m_map[4][8] == 48
m_map[4][9] == 49
Hope the above helps.
Thanks,
Bio.
|
|
|
|
|
hi...I am new in the field of ATL...Please suggest some books which take the reader from Beginning to programming stage...
thanks...
utkarsh sharma
"Not everything that counts can be counted, and not everything that can be counted counts."
|
|
|
|
|
The best ATL book so far I've read is ATL Internals[^], by Brent Rector and Chris Sells.
That book together with Essential COM[^] by Don Box is a perfect combo for learning COM. If you're new to COM, I'd suggest you start with Essential COM.
--
You're entertaining at least.
|
|
|
|
|
thanks..for the names ATL Internal and Essential COM...
utkarsh sharma
"Not everything that counts can be counted, and not everything that can be counted counts."
|
|
|
|
|
Hi,,
I make an activeX Control using ATL
I added a full control with the font stock property..
now i want to get notified when this property changes..(after the user changes the property i want to perform some action)...
how can i do this ?
|
|
|
|
|
Take a look at the CStockPropImpl source code (atlctl.h). There you will find code like this:
HRESULT STDMETHODCALLTYPE put_Font(IFontDisp* pFont)
{
...
__if_exists(T::OnFontChanged)
{
pT->OnFontChanged();
}
...
} So, for the property Font you add the OnFontChanged function. For the property Picture, you add OnPictureChanged, etc.
--
They say the most horrible things, but I hear violins.
When I close my eyes, I'm at the center of the sun.
|
|
|
|
|
thank you for the reply but i revised put_Font and it does not contain that code ..
Do you use ATL 7.0 ?
I use ATL 3.0 with VC++6 and I need to implement this functionaliy..
Can you help with this ?
maybe by implementing the OnChange(DISPID) function of IPropertyNotifySink..
Can you help me with this ?
|
|
|
|
|