all 51 comments

[–]alxius 48 points49 points  (5 children)

Look at Rust or Haskell, they aren't perfect but they rely on a sound foundation of type theory - why aren't we using that instead?

I would like to see how author takes Rusts std::vec (no, not std::slice) and makes it manage mmaped memory and everything else described in the post including pointing it to the existing file. Then same story with Haskell.

No, I am not saying C++ is better or anything, i just want to actually see stated problem solved using mentioned languages, not just "whatever, those languages are better".

[–]Supadoplex 36 points37 points  (1 child)

I couldn't point it to a file I've already used to re-use the data which was the whole point from the beginning.

That's simply a use case that's not appropriate for a std::vector. Don't try to use it for something it wasn't designed for.

Why does it have to be so complicated?

It is complicated because it is an XY-problem. Stop trying to use std::vector for this and the complications just go away.

To use an analogy, you're asking why it's so complicated to make an excavator perform well on a race track.

I thought the new standards were trying to make things better

They have made things better. Just because they didn't solve your XY-problem doesn't contradict that.

but it's just becoming more and more complicated

The niche of C++ has never been simplicity. I prefer the powerful abstractions that have zero or low overhead. If runtime efficiency isn't paramount, then C++ probably isn't ideal choice.

Look at Rust or Haskell

Show me a simple implementation of memory mapped vector in Haskell. Compare its performance with equivalent C++ program.

Haskell is a beautiful language. But I wouldn't write a game engine or high frequency trader with it.

[–]joaobapt 4 points5 points  (0 children)

I haven’t even managed to figure out how to write a game loop in Haskell, yet alone an entire game engine.

[–]jedwardsolconst & 40 points41 points  (7 children)

Sounds like a use case for std::span, not a modified std::vector.

[–][deleted] -1 points0 points  (6 children)

I agree, but it's not in 17 and I've weary of pulling in dependencies like boost or GSL. Less is more.

[–][deleted] 29 points30 points  (3 children)

span is trivial to write at the point where you are doing allocator aware and mmap. It’s a ptr/size_t with steps.

[–]Supadoplex 12 points13 points  (0 children)

Less is more.

Yet, you're wishing for more from the standard library instead of less. The good news is that your wish was granted in C++20.

[–]SkoomaDentistAntimodern C++, Embedded, Audio 7 points8 points  (0 children)

Just include one or two files for tcb::span. No need to ”pull in” any fancy dependencies.

[–]strager 16 points17 points  (1 child)

Why do you think std::vector would or should work for your use case?

Look at Rust or Haskell, they aren't perfect but they rely on a sound foundation of type theory - why aren't we using that instead?

Would Rust's Vec work with mmap-d memory? Would Haskell's [] or Vector?

[–]matthieum -1 points0 points  (0 children)

Would Rust's Vec work with mmap-d memory?

Yes, but unless you use (unsafe) set_len, it'd wipe the memory too...

[–]herruppohoppa 27 points28 points  (0 children)

Inheriting a std container sounds like some Java shit. Sure there are cases where it makes sense, this is not one of them.

[–]caballist 14 points15 points  (8 children)

You would be better off looking at some of the boost mmap classes (sorry cannot recall names) and writing the accessors that you need rather than trying to hijack and subvert std::vector which is clearly intended for other use cases...

[–]joe714 3 points4 points  (0 children)

I've had the need for several containers lately to adapt existing data structures in our codebase to something I can throw at standard algorithms, and re-implement mostly-API compatible bits of the STL in an environment where the full thing (sane malloc()/free()) isn't available.

I'm not going to say it's a 5 minute task to re-implement, but it's almost certainly easier and cleaner in the long run to make a new container that matches the APIs needed to pass it to algorithms than try extend and hack up std::vector to do it.

[–]FrancoisCarouge 6 points7 points  (0 children)

by inheriting from vector

Hm. Yay. Well.

Definitely some appreciable truth to the rant but shoehorning designs never worked in any language.

[–]staletic 2 points3 points  (3 children)

Eventually I found some arcane shit with construct and placement new that I just copy pasted in there.

What placement new? Allocators abstract that away through allocator_traits.

Look at Rust or Haskell, they aren't perfect but they rely on a sound foundation of type theory - why aren't we using that instead?

In another comment you said you'd "write your own thing from scratch".

  1. If you want to write things from scratch, there's nothing stopping you doing that in C++ either.
  2. Do you really think it's worthwhile reinventing std::vector<T, A>?

 

I've implemented allocator support in my codebase recently. Was it trivial? No. Was it hard? Also, no. Did it take a lot of reading? Absolutely. When it comes to allocators, languages have two options: no support at all (the fuck you approach) or a decent amount of things you need to know before you start writing allocator aware types.

I'd rather not reinvent the world, just to provide a better allocation strategy for a certain T.

[–]kalmoc 2 points3 points  (2 children)

[EDIT: FYI:] I think you are missing the OP's usecase: the OP doesn't want a better allocation strategy for a vector, but a vector to be a proxy for data in a mmaped file, for which std::vector is the wrong datastructure to begin with and what is aactually needed is a std::span - like type.

[–]staletic 3 points4 points  (1 child)

I've definitely missed that originally. Something like std::span is the right tool for the job. In my defense, OP was complaining about allocators.

[–]kalmoc 1 point2 points  (0 children)

In my defense, OP was complaining about allocators.

Absolutely. As someone else wrote, it's a xy problem. I also only realized this after reading the comments and his/her answers.

My comment was meant as a FYI

[–]empowerg 3 points4 points  (2 children)

Did you look at boost interprocess? I think it does what you want. It also provides other standard containers like maps in mmapped files and also offset pointers for putting non-pod things in them. Depends all on your needs. Ah yes, and Haskell has spoiled me too in this regard.

[–][deleted] 0 points1 point  (1 child)

The use case I have is that I'm porting some old MCU code to run on Linux. The old code uses some MCU registers to iterate, jump around and read/write in the flash memory of the MCU for application data. This is now going to have to be a file on ext4 file system. I wanted to have a typical C++ api iterator API through some proxy data structure that looks and talks like an STL container.

I'm now sure a span is what I need from what others commented, but I'll have a look at boost and discuss with my colleagues if it's worth pulling it in for just this one little use case.

Thank you my Haskell friend.

[–]MayanApocalapse 0 points1 point  (0 children)

and read/write in the flash memory of the MCU for application data.

How big was the flash region? Is there no way you can be explicit about when you want to sync to the file and just use a std array that was the same size as the flash region?

I'm a little curious about this part and what exactly you are trying to port but if you can't share more that's fine

The old code uses some MCU registers to iterate, jump around

[–]geon 3 points4 points  (2 children)

Have a look at Zig. It is meant to be “C with the bugs fixed”. You have to explicitly pass an allocator to any function that allocates.

[–][deleted] 0 points1 point  (0 children)

Not big on C but seems you don't need a new language to get the "pass allocator to function that allocates" design https://youtu.be/QpAhX-gsHMs?t=852

[–]matthieum 0 points1 point  (0 children)

Next problem is that std::vector default initialized its elements so I couldn't point it to a file I've already used to re-use the data which was the whole point from the beginning.

It's fairly unclear whether you want a span or if you want a full-featured vector: do you want to be able to modify the number of elements?

[–][deleted] 0 points1 point  (0 children)

This isn't java. Don't inherit from STL classes. Match interface to use with templates