8 ms·
> many "enterprisey megacorps" seem to apply a restricted subset of C++ rather successfully Your definition of 'successfully' is vastly different from the Mega
by otabdeveloper1 11y ago
> many "enterprisey megacorps" seem to apply a restricted subset of C++ rather successfully
Your definition of 'successfully' is vastly different from the Megacorp definition of 'successfully'. I interview C++ programmers _all the time_, and let me tell you: practically the only reason those restricted subsets of C++ exist is to allow bad programmers to work at Megacorp.
There are a lot of really unqualified C++ programmers in the world, and by far the biggest problem faced by Megacorp is employee churn, not code quality and not product deadlines.
The use of 'C++ subsets' solves the employee churn problem at the cost of code quality.
- p0nce 11y agoAgreed. If you are using C++ but no exceptions, no RAII, and no std::unique_ptr, you are avoiding the best part of C++.
- vvanders 11y agoI'm with you on RAII and unique_ptr but I've yet to find exceptions to be compelling enough. I find Rust's approach(Result<T,E>) much nicer.
- lmm 11y agoThe functional approach is great in a language with typeclasses or modules. But it's not a good fit for RAII - how would a C++ constructor report an error using Result?
- vvanders 11y agoBy not doing any work in the constructor. IMO constructors should be setting sane defaults and nothing more. If you need to do work that could fail put that into an "init()" function with a return type that can signal an error. I worked for quite a while on platforms that didn't have exceptions and this was the standard pattern for keeping RAII without needing them. If you wrap the return value correctly(like with Result<T,E>) you can also guarantee that your clients need to deal with the error case(or fail to handle it with unwrap()) as opposed to getting caught by an exception that wasn't declared or documented.
- lmm 11y ago> IMO constructors should be setting sane defaults and nothing more. If you need to do work that could fail put that into an "init()" function with a return type that can signal an error. That allows you to construct the object in an invalid state. The whole point of RAII is to avoid that. The acronym literally means not having a separate init() function.
- vvanders 11y agoSorry, I should have clarified that the init function is usually static so you can invoke with it returning an object + possible error code if you never want an object in an invalid state. FWIW some quick googling shows that having a constructor acquire a resource is not a requirement(https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Resource_Acquisition_Is_Initialization#Solution_and_Sample_Code https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Resource_A...). The important part about RAII is that the automatic releasing of resources when out of scope(through a no-throw destructor).
- Manishearth 11y agoYou can solve this problem the Rust way too: don't use a constructor. Create a static `new` method that returns the object to you, with optional error flags. This is still RAII, you're just not using a constructor to acquire. Rust doesn't have constructors and is still RAII.
- pjmlp 11y agoWhile I also don't like the exception handlers in constructors syntax, not putting any work in the constructor doesn't mean that data members or base classes cannot fail to initialize.
- steveklabnik 11y agoIn Rust, we don't have special constructors, just functions, and to construct a struct, all of its members must be valid, and assigned at the same time. So a Rust-style "constructor" in this vein would return a Result<MyStruct, Error>, basically.
- stinos 11y agoI've been looking for something similar for C++ for a while now, after getting fed up with yet another prototype like bool OpenFile( const std::string& path, File& f, std::string& err ) or similar, you get the point. At the moment I'm using a class like llvm's ErroOr<T> [1] and I'm loving it so far. The aformentioned function would be written as ErrorOr<File> OpenFile( const std::string& path ) and contain an std::error_code if opening failed, or else a File instance. [1] http://www.llvm.org/docs/doxygen/html/classllvm_1_1ErrorOr.html http://www.llvm.org/docs/doxygen/html/classllvm_1_1ErrorOr.h...
- vvanders 11y agoYup, this is exactly like Rust's Result<T,E>(with E being std::error_code).
- lorenzhs 11y agoThat's a very useful pattern, functional languages often call it the maybe monad. I wish more people used it in other languages. This is my version of it: https://github.com/lorenzhs/algen-framework/blob/master/common/maybe.h https://github.com/lorenzhs/algen-framework/blob/master/comm...
- stinos 11y agoThat's actually std::optional, minus the nothing/just notation? Indeed more people should use things like this. Reminds me of a similar concept I also have wrappers for: instead of manually having to compare the results of std::find etc against range.end() all over the place, the result is basically in a small container which has both the iterator returned and the end of the range. So I write const auto result = alg::find( range, pred ); if( result ) doStuff( *result ); //*result is reference to found element instead of typcial const auto end = range.cend(); const auto result = std::find( range.cbegin(), end, pred ); if( result != end ) doStuff( *result ); Not that much of a gain, but once used to it I could never go back. And I realize now this could actually just be rewritten using your maybe class or std::optional.
- 11y ago
- p0nce 11y agoWe are seing lots of .unwrap() because Rust has no monadic notation. That replaces recoverable errors with crash.
- kibwen 11y agoI don't think monadic notation here is the panacea that it is sold as. The harder part would still be modifying your function's return type to thread the result up the stack. In any case, .unwrap() is perfectly fine in applications, it's only in libraries that they're discouraged.
- _yosefk 11y agoWell, your definition of bad C++ devs may differ from mine or Google's. Or it might not, but for all I know, you might require knowledge of arcana that I don't care about, even when I happen to know it. To me success includes being able to find (not frequently replace - I like working with the same people for many years - but find new ones in order to grow) developers that can contribute to the code base, and some of the best ones I know can't be bothered to learn much of C++. Go figure. Maybe you and I legitimately disagree because we work on different things, and maybe one of us is wrong.