6 ms·
It doesn't solve the problem because you'd have move to 2 stage construction/initialization and that creates even more problems than this.
by wvenable 10y ago
It doesn't solve the problem because you'd have move to 2 stage construction/initialization and that creates even more problems than this.
- vvanders 10y agoNope, if you have an operation that can fail then wrap it in a type that represents that(I'm partial to Rust's Result<T,E>) then you force consumers to deal with potential errors and you can do 1-call construct + init if you want to. Exceptions cause all sorts of problems(like violating the principal of only paying for what you use). They aren't checked so you can't enforce handling via type system and in general they're just a mess in C++.
- Arnavion 10y agoC++ constructors can't return error codes or Result. That's the two-stage initialization (constructor call + initialize() call) wvenable is talking about. (Of course you could do the same thing as Rust and expose only a static creator function and hide the actual constructor.)
- vvanders 10y agoYeah, most projects I worked on was doing the static creator before Rust showed up on the scene since it sidesteps a lot of these issues.
- int_19h 10y ago> Exceptions cause all sorts of problems(like violating the principal of only paying for what you use). Exceptions are zero-cost in terms of performance on any sane architecture (this excludes x86, but not x64). The only cost that you're paying is the extra memory for the tables, which are all statically allocated.
- vvanders 10y agoDon't you need RTTI as well? That's not been zero-cost on all compilers I've used in the past.
- int_19h 10y agoYou do, but C++ includes RTTI separately from exceptions (dynamic_cast and typeid), so it's going to be there regardless. If you turn it off, then we're not talking about standard C++ anymore, but some subset.
- wvenable 10y agoWhen you throw and exception, C++ compilers add RTTI for those classes even when RTTI is separately disabled. You cannot call dynamic_cast and type_id but the generated code is the same. I don't really see this as much of an issue given you have to have this RTTI to catch the exception properly.
- int_19h 10y agoMy point is that RTTI is required by other things in the C++ standard, not just exceptions. So it's still "free" if we're only considering exceptions separately by themselves, and leave all other features as they are in standard C++ (and if you disable RTTI entirely, then you no longer have standard C++, since those other features also stop working). If we consider the combo of exceptions+RTTI, then yes, dropping both at the same time lets you get rid of some further overhead (although again it's memory-only, not compute cycles). But then we have to discuss the lost benefits of those other features, not just exceptions alone, to judge whether doing so is worthwhile or not. BTW, I may well be wrong here, but isn't RTTI generation for exceptions (when it's otherwise disabled) an example of "only pay for what you use"? i.e. wouldn't the compiler then only generate RTTI entries for those types that are either thrown somewhere, or are caught somewhere? If so, any library code that doesn't throw itself, and only needs to allow exceptions to pass through it, is still zero-overhead in that regard.
- 10y ago
- saghm 10y agoIn terms of memory usage for similar Result type in C++, is there any way around allocating the space for both types (as opposed to Result in Rust, which just allocates enough space for the larger of the two)? My understanding is that there is not, although I'm still not very experienced with C++, so I wouldn't be surprised if I'm wrong
- vvanders 10y agoYou can use a union + tag(which the same as Rust uses which is why they're called Tagged Unions) however you run into issues with constructors/destructors. You can do something similar with placement new/delete but it requires some hoops. Honestly most error codes are small enough that you can just pay the hit for it on the stack and discard it once you've handled the good/bad case.
- gpm 10y agostd::variant with c++17, but on linux at least you need to install gcc from git to have access to it so far. boost::variant otherwise, but depending on the types used (if there aren't any that are nothrow default constructible) it allocates on assignment. If you just want a result type and not a more general "rust enum", this repository does it (while only allocating space for the larger, I think) https://github.com/oktal/result/ https://github.com/oktal/result/ And I don't think there's any reason you couldn't implement an equivalent of std::variant for previous versions of C++, I'm just not aware of any.
- irishcoffee 10y agoHeh, I implemented an in-house variant at work a week ago. As it turns out, I was able to use my variant class in a python extension I developed. Also, as it turns out, python is scary in what it lets you get away with when developing extensions.
- petters 10y agoExceptions are typically faster than error codes when errors are rare.