# C++ How to memcpy std::map values to a pointer?

## Recommended Posts

Posted (edited)

I have a std::map<int, Point> keyed by the points id. I need to do the equivalent of a memcpy into a pointer like the following.

struct Point {
float x, y, z;
float nx, ny, nz;
};

// ...

std::map<int, Point> meshA = submesh.at(2);

Point* points = reinterpret_cast<Point*>(OGRE_MALLOC_SIMD(sizeof(Point) * totalPoints(), Ogre::MEMCATEGORY_GEOMETRY));

// memcpy into points?


After allocating the memory, how does one do the equivalent of a memcpy of std::map<int, Point> into 'Point* points'? I have to populate this pointer (Point *) which is the type my engine API takes.

Edited by SR D

##### Share on other sites
Posted (edited)

Do you just want the 'Point' instances from the map, without the IDs? [Edit: I'm guessing that's the case based on the use of 'Point *', but it might still be worth clarifying that.] And does order matter? (E.g. do you want the points ordered by ascending ID?)

Edited by Zakwayda

##### Share on other sites
Posted (edited)

Yeah, I should have clarified that.

No, the point id's wouldn't be a part of it. Just the point structures. Yes, order does matter.

Edited by SR D

##### Share on other sites

Assuming the order you want is by ascending ID, then I think you'll need to iterate over the map and process each 'Point' instance one at a time (either implicitly or explicitly - there are various ways you could express it using standard library features).

There may be other issues involved, such as padding, alignment, reinterpret_cast vs static_cast, and so on, but I don't know much about the context you're working in, so I won't comment on those issues. It sounds like the key question though is how to extract the 'Point' instances from the map, and I think the answer is that, one way or another, it needs to be done one at a time.

##### Share on other sites

I think you need to question why you have an std::map<> from int to Point in the first place... but assuming it's working fine for you, what's wrong with...

void populate_raw_array(Point * &dest, int & maxN, std::map<int,Point> source const) {
if( maxN > source.size() ) maxN = source.size();
for (auto dp = dest, i = source.begin(), n = maxN; n != 0; ++dp, ++i, --n) {
*dp = i->second;
}
}

// Usage...
Point buffer[256];
int size = 256;
populate_raw_array(buffer, size, my_map_of_points);
// buffer[0] through buffer[size], exclusive, now have points in.

##### Share on other sites

You could way more simple store all your points in memory and have the map just point to an Integer to Point-Pointer pair instead of to just the Point instance itself

##### Share on other sites

Using SIMD implies you need the points in contiguous memory, which a map does not have.

You could use std::transform() from the map to the SIMD memory using a simple lambda to get the second member of the map pair.

transform(begin(meshA), end(meshA),
back_inserter(points),
[](map<int,Point>::value_type const& mp) -> Point
{ return mp.second; });

You could also use a loop.

auto p = points;
for (auto const& mp: meshA)
*p++ = mp.second;

There is no more efficient way.

Note that std::map is a sorted associative container, so no fancy sorting is necessary, unless your desired sort order differs from the one you're sorting the map by.  In that case, std::sort is your best friend, but you might also consider why you're using a sorted associative container in the first place if you're not using the sort order of the container.

## Create an account

Register a new account

• 18
• 25
• 11
• 21
• 16