7 ms·
> I do believe that a C++ regex library written in reasonable time using normal development practices will have memory safety problems in it. This is based on t
by civility 10y ago
> I do believe that a C++ regex library written in reasonable time using normal development practices will have memory safety problems in it. This is based on the real-world experience we have with C++ projects.
Me too. I'm guessing the JavaScript RegExp types in Firefox and Chrome are pretty battle hardened at this point though. I submit those as existence proofs that it could be possible. However, I'm sure they've had their exploitable bugs along the way, and I would guess the code is now ugly.
For what it's worth, I would never submit all of boost as a shining example of clean and modern C++. There are gems in there, but there is a lot of cruft too. I think the biggest benefits it has brought to the C++ world is as a testing ground for new ideas and as a compiler stress test. Some parts of boost are practically a fuzz test for finding the bugs in g++ and clang++. :-)
> If your project is 5% unsafe code and 95% safe code, that's a win
Unfortunately for me, it was the first 5%, and honestly I'd call it more like 20%. It was a weekend learning project, and all I wanted to do was create a freshman level data structure from scratch. I had already had other successes, so this seemed like a good next step, but it wasn't. The weekend passed, and what I really learned was to expect more pain the next time I want to write a low level data structure in Rust.
> I don't agree that it's broken.
I can't make you agree - we might be in opinion territory. It's certainly broken in my opinion.
I have been following along in the various blog posts and forum discussions. It seems like some of your coworkers think the rules are overly restrictive, so broken or not, it looks like they're trying to fix it at least a little. Unfortunately, I don't think they're very concerned about my particular use cases (and maybe they shouldn't be).
> In order to "fix it", we'd either have to throw out generics in favor of C++/D-style templates or have Haskell-like overlapping instances link errors.
I don't think those are the only two options, but you might find the other options even more unpalatable.
> In general, I find issues with the expressiveness of generics are often overblown.
I think all this says is that you don't write very much of the kind of code which benefits from generics. You can dismiss my point of view, but some of us do use them a lot, and it's one of the driving reasons I use C++.
Generics are a documented feature of Rust, but every time I try to use them I hit a wall and end up falling back on the (admittedly powerful) macro system. If I write a library, should I tell my users they need to invoke my macros for use with their types? This is exactly the use case for generics.
(I suspect I need an obligatory smiley here to let you know it's still a friendly discussion :-)
> Remember that people write all sorts of software in Go, which doesn't have generics at all
People write all sorts of software in all sort of languages. That doesn't say much one way or the other.
Go seems really nice in some ways. The learning curve looks small, so I don't think it would frustrate my coworkers like Rust would. However, if I tried to bring it to work I'd need some sort of code generator to avoid the multiple maintenance for functions that work on float32, float64, complex64, complex128 and so on.
Maybe they'd consider adding a macro facility like the one in Rust to work around the deficiencies in the language. :-)
Besides, Go has GC and some of our software already needs a lot of memory. The pause times might be getting pretty good, but I'm guessing the memory foot print would be at least twice what it is in C++. (I should measure that though.)
> , much less overlapping instances!
Disclosure: I don't really know what an "overlapping instance" means in this context. It might be possible we're talking about different deficiencies in Rust generics, and I just don't have the right vocabulary.
- Manishearth 10y ago> It was a weekend learning project, and all I wanted to do was create a freshman level data structure from scratch. It's worth mentioning that the implementation difficulty of data structures in Rust is not representative of the general difficulty of programming in Rust. Just because this is hard doesn't make it a bad language. Rust's philosophy is that you deal with the trouble of writing unsafe code each time you need a new low level abstraction, and when done, you don't have to worry about it again. Also, writing generic datastructures in C++ without falling afoul of UB, and/or getting destruction semantics right can be quite tricky. Rust ... really doesn't have additional issues here; raw pointers in Rust work the same way as in C++, except they're a tad verbose. The only difference is that in Rust you probably want to provide a safe API, whereas in "freshman C++ datastructures" the datastructure does not have the unsafety neatly encapsulated. This is a hard task in both Rust and C++, especially with generic datastructures. Writing datastructures isn't really a common task. It's a "simple" task because it's simple in C and C++, but here's no real reason it has to be in Rust. You can write inefficient datastructures in 100% safe Rust without too many problems, much like you can implement datastructures in regular-joe Java. Writing efficient, low-level datastructures can be pretty hard, but like I said it's a rare task so not much of an issue. http://cglab.ca/~abeinges/blah/too-many-lists/book/ http://cglab.ca/~abeinges/blah/too-many-lists/book/ and https://doc.rust-lang.org/nomicon/ https://doc.rust-lang.org/nomicon/ are pretty good resources about writing unsafe Rust. The exact boundaries and semantics of unsafe code are still being pinned down so while I do want to improve this documentation I'm waiting for that to happen first. In general I advise folks to not write unsafe Rust till they are sure that they have a clear grasp of safe Rust. But if you want I can have a look at what you tried and help you improve your design. I'm very interested in making such things more accessible (on one hand, the Rust community doesn't really want to encourage the use of unsafe code, on the other hand, sometimes you need it and it would be nice if it was easier for people to use when that situation arises) so learning what people stumble on is important to me. > Unfortunately, I don't think they're very concerned about my particular use cases (and maybe they should > > I think all this says is that you don't write very much of the kind of code which benefits from generics. You can dismiss my point of view, but some of us do use them a lot, and it's one of the driving reasons I use C++. It seems like you're using generics the way you use templates for metaprogramming in C++. I totally get how powerful TMP is (I love to use it myself, though I can get carried away), but be aware that Rust is a different language and you have to approach it differently. It's important to consider the limitations of the system when designing a solution -- if I designed a solution for C++ and implemented it in Rust, I'd hit problems in the last mile and find it very annoying to make it work (using macros or something to fill in the gap). However, if you design the code from the start with Rust's advantages and limitations in mind; you may come up with a different but just as good system. This is something I hit every time I learn a new language. I hit it with Rust, Go, and many years ago, C++. So it may help to approach the language with a fresh mind. Yes, coherence is painful. I seem to hit coherence issues pretty rarely myself, but they're annoying when they happen. There's work going on to improve these pain points (specialization!), but it's overall not that big a problem. I think an example of what you tried might help. Preferably a more holistic example, condensed minimal examples tend to hide instances of the XY problem. > Disclosure: I don't really know what an "overlapping instance" means in this context. cases where you have more than one implementation that make sense for a given call. C++ solves this by allowing things to overlap and introducing overload resolution rules. Rust solves this by not allowing overlap. > but I'm guessing the memory foot print would be at least twice what it is in C++. (I should measure that though.) Go does make extensive use of the stack and has decent escape analysis, so it might not be that bad, really. But measuring it is probably the best way to go here. > Some other time it's because the standard library doesn't have a trait for a commonly implemented method, so I can't write a generic function to call that method. Do you have examples? In some cases generic methods are outside the stdlib in different crates, e.g. num_traits.