Map problem

T

tech

Hi, I want to create a map of named events from a const array.

eg std::map<std::string, HANDLE> this needs to be intialised so that

initially it will be contain the names of the all the events with a
NULL handle then
i can do the following

std::map<std::string, HANDLE> Events;
std::map<std::string, HANDLE>::iterator it;

const std::string[] { "EventName1", "EventName2", "EventName3"};

it = Events.begin();

while (it != Events.end())
{
Events[it->first] = CreateEvent(NULL,FALSE,FALSE, it->first.c_str())
++it;
}


So i f i ever need a new event all i need to do is add it to the array
and the event will be created
managed, destroyed just using the map.

However do i use the string array to initalise the map keys however?
 
J

Jim Langston

tech said:
Hi, I want to create a map of named events from a const array.

eg std::map<std::string, HANDLE> this needs to be intialised so that

initially it will be contain the names of the all the events with a
NULL handle then
i can do the following

std::map<std::string, HANDLE> Events;
std::map<std::string, HANDLE>::iterator it;

const std::string[] { "EventName1", "EventName2", "EventName3"};

I think you meant to give this a name. Something Like:
const std::string EventNames[] { "EventName1", "EventName2", "EventName3"};
it = Events.begin();

while (it != Events.end())
{
Events[it->first] = CreateEvent(NULL,FALSE,FALSE, it->first.c_str())
++it;
}


So i f i ever need a new event all i need to do is add it to the array
and the event will be created
managed, destroyed just using the map.

However do i use the string array to initalise the map keys however?

Simplest would be something like:

for ( int i = 0; i < sizeof( EventNames ) / sizeof( EvenNames[0] ); ++i )
Events[EventNames] = NULL;

the sizeof( Eventnames ) / sizeof( EventNames[0]] may be a little off. Thsi
just is to determine how many names are in the array.

But really, for a constant array of text I'd just go with a char*[]

const char* EventNames[] = { "EventName1", "EventName2", "EventName3"};

Notice that this isn't using C style char arrays, but an array of character
pointers.
 
M

Michael.Boehnisch

tech said:
Hi, I want to create a map of named events from a const array.
However do i use the string array to initalise the map keys however?

Simplest would be something like:

for ( int i = 0; i < sizeof( EventNames ) / sizeof( EvenNames[0] ); ++i )
Events[EventNames] = NULL;


Alternatively, you may change the EventNames[] array to
std::pair<std::string, HANDLE>:

typedef std::pair<std::string, HANDLE> Pair;

Pair EventNames[] = {
Pair( "EventName1", 0 ),
Pair( "EventName2", 0 ),
...
};

This looks more ugly at first (the typedef enhances usability a
little). However, you now can do the initialization like this:

std::map<std::string, HANDLE> Events(
&EventNames[0],
&EventNames[ sizeof EventNames / sizeof( Pair ) ]
);


This avoids explicit loops and can be used in a constructor
initializer list. Its a mere matter of taste.

best,

Michael
 
T

Thomas J. Gritzan

tech said:
Hi, I want to create a map of named events from a const array.

eg std::map<std::string, HANDLE> this needs to be intialised so that

initially it will be contain the names of the all the events with a
NULL handle then
i can do the following

std::map<std::string, HANDLE> Events;
std::map<std::string, HANDLE>::iterator it;

const std::string[] { "EventName1", "EventName2", "EventName3"};

const std::string eventNames[] = { "EventName1", "EventName2", "EventName3"};
it = Events.begin();

while (it != Events.end())
{
Events[it->first] = CreateEvent(NULL,FALSE,FALSE, it->first.c_str())

Since 'it' already refers to the pair of std::string,HANDLE you want to
access in the map, just use:
it->second = ...
instead of
Events[it->first] = ...

But because you want to fill the map with the array, you would want to loop
over the array and not over the map content, as Jim Langston wrote.
So i f i ever need a new event all i need to do is add it to the array
and the event will be created
managed, destroyed just using the map.

Wrong. The map doesn't know how to destroy the events. You will have to
loop over the map elements and call the right function to destroy the
events as documented with the CreateEvent function.
The map will only destroy, and release memory for, the HANDLE.
 
J

Jerry Coffin

Hi, I want to create a map of named events from a const array.

eg std::map<std::string, HANDLE> this needs to be intialised so that

initially it will be contain the names of the all the events with a
NULL handle then
i can do the following

std::map<std::string, HANDLE> Events;
std::map<std::string, HANDLE>::iterator it;

const std::string[] { "EventName1", "EventName2", "EventName3"};

it = Events.begin();

while (it != Events.end())
{
Events[it->first] = CreateEvent(NULL,FALSE,FALSE, it->first.c_str())
++it;
}


So i f i ever need a new event all i need to do is add it to the array
and the event will be created
managed, destroyed just using the map.

However do i use the string array to initalise the map keys however?

I'd start by writing a wrapper class for the events:

// warning: untested code.
class event {
HANDLE ev;
public:
// You usually don't want to name events unless you're sharing them
// across process boundaries.
event() : ev(CreateEvent(NULL, FALSE, FALSE, NULL) {}

// haven't thought a lot about this -- might cause problem when copying
// an event. They're really more "identity" than "value" objects.
~event() { CloseHandle(ev); }

DWORD wait(DWORD time = INFINITE) {
return WaitForSingleObject(ev, time);
}
};

Then you can put events into your map a bit more directly:

std::map<std::string, event> events;
char const *names[] = {"Event1", "Event2", "Event3"};

#define elements(x) (sizeof(x)/sizeof(x[0]))

for (int i=0; i<elements(names); ++i)
events.insert(std::make_pair(names, event()));
 
T

Thomas J. Gritzan

Jerry Coffin wrote:
[putting an Windows event HANDLE into a std::map]
I'd start by writing a wrapper class for the events:

// warning: untested code.
class event {
HANDLE ev;
public:
// You usually don't want to name events unless you're sharing them
// across process boundaries.
event() : ev(CreateEvent(NULL, FALSE, FALSE, NULL) {}

// haven't thought a lot about this -- might cause problem when copying
// an event. They're really more "identity" than "value" objects.
~event() { CloseHandle(ev); }

DWORD wait(DWORD time = INFINITE) {
return WaitForSingleObject(ev, time);
}
};

Then you can put events into your map a bit more directly:

std::map<std::string, event> events;
char const *names[] = {"Event1", "Event2", "Event3"};

#define elements(x) (sizeof(x)/sizeof(x[0]))

for (int i=0; i<elements(names); ++i)
events.insert(std::make_pair(names, event()));


Remember the Rule of three? The standard container require the elements to
be copyable.

One could use a std::shared_ptr for this.
 
J

Jerry Coffin

[ ... ]

[ ... ]
Remember the Rule of three? The standard container require the elements to
be copyable.

One could use a std::shared_ptr for this.

Obviously I remembered that they need to be copyable, but didn't go much
beyond that (e.g. to making the code work). :)

You could use a shared_ptr, or you could use DuplicateHandle. A
shared_ptr is probably more idiomatic C++, while DuplicateHandle is
probably more idiomatic Win32. Most like a shared_ptr is faster though
(since it avoids an OS call).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top