6 ms·
Yeah it seems... odd. I fully get preferring return codes to exceptions, but you can still just do that in C++? Heck, you can trivially do a type-safe union of
by kllrnohj 8y ago
Yeah it seems... odd. I fully get preferring return codes to exceptions, but you can still just do that in C++? Heck, you can trivially do a type-safe union of return value or error code in the spirit of Rust in C++.
And you can do things like enforce that the return value is used by checking in the destructor if the return value was unwrapped.
Similarly for constructors if you have an object that can fail construction instead of doing what the author suggested of
class foo {
public:
foo ();
int init ();
...
};
You could instead do something better like:
class foo {
private:
foo ();
int init ();
...
public:
static std::optional<std::unique_ptr<Foo>> create();
};
This is a well-established pattern in languages like Java, for example, to do exactly what the author wants - a constructor that can fail without forcing callers to just know they need to try/catch.
- Gibbon1 8y agoYou can use a returned stucts in c to pass both an err code and a value typedef struct { int err; int value; } rtn_t; rtn_t rtn = foo(); if(rtn.err < 0) printf( "err=%i", rtn.err); else printf( "value = %i\n", rtn.value);
- Koshkin 8y ago> both But only one of them would make sense at a given moment, so why waste memory?
- AnimalMuppet 8y agoSo that at any given moment, you know which one you have.
- Koshkin 8y agoThat requires 1 bit of information, and there is often a way of embedding that bit in the value itself; but the general technique of representing alternatives is called “a tagged union.” (You can also hear the fancy terms “the product type” for the struct and “the sum type” for the union.)
- lixtra 8y agoAccessing that one bit can be as expensive as passing an int around.
- kllrnohj 8y agoYour example doesn't tell me which I have. It's assuming that err = 0 means success, but that's an assumption not a contract of the type. By comparison some something like https://github.com/oktal/result https://github.com/oktal/result will tell you if it's a success or error without any magic error codes that actually mean success. You could do this with a type bit + union in C, it's just more painful without templates
- Gibbon1 8y ago> so why waste memory? In c it'll be either in a register or on the stack.
- dkrikun 8y agoThere are certain widely accepted norms on how to handle errors in C. It is best to restrain ourselves to "prior art" so that your code is immediately comfortable to read and use for a seasoned C dev. To list a few: return codes, errno and longjump
- int_19h 8y agoDon't use setjmp/longjmp unless you can guarantee that you own all frames between one and the other (i.e. don't use it as a public error reporting API in a library, for example). They don't play well with C++, and really anything else that needs to unwind the stack. Those who write R extensions in C++ know how messy it can be.
- SamReidHughes 8y agoThe only widely accepted one in that list is return codes.
- Gibbon1 8y ago> a seasoned C dev. To list a few: return codes, errno and longjump A seasoned dev that thinks errno and longjump are good idea's should have retired 25 years ago.
- dkrikun 8y agoYeah, I just tried to be on the more "permissive" side of things. Though per-library errno is being used (zeromq, libuv).
- seba_dos1 8y agoOf course you can do various things in various languages, but good luck getting any adoption of a library that goes against the language idioms in its language. You expect certain kind of API from C libs, certain one from C++, and different one from Java packages. If C idioms work better in your project, just go for C. You get other advantages from that, like faster compile times and being independent from C++ stdlib, which can be messy at times (not even speaking about Boost). You don't have to stay with C++ just because somebody else (or even you) thinks that it's generally a better language.
- kllrnohj 8y agoRoughly ~50% of the C++ ecosystem compiles with -fno-exceptions[1]. So using return values instead of exceptions is not against the language's idioms at all. It's one of the reasons std::nothrow exists, after all. Similarly while exceptions are part of the Java idioms, it does after all have checked exceptions even, it's incredibly common to not use that idiom on constructors, where it's weird. Just because a thing is an idiom in some cases doesn't mean it's the expected idiom in ALL cases. And if an idiom is dumb it doesn't mean you should just do it to follow along with the dumb, nor should you go to a language where you're forced to be less safe & less clear just because "but mah idioms". Be the change you want to see. 1: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r0.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p070... has the survey data (along with a language proposal to make return-value exceptions a proper C++ feature)
- Koshkin 8y agoHmm... Do you really need to wrap a pointer in std::optional?
- int_19h 8y agoIt forces anyone trying to use it to contemplate the no-value case.
- kllrnohj 8y agoReplace the pointer with a value type and now you'd see why the optional is necessary. Similarly I'd probably substitute the optional with a variant that has the actual error code. Go nuts with whatever you want here.
- Koshkin 8y ago> Go nuts Let's make error code optional, too.
- shaklee3 8y agoTo be fair to the author, std::optional was added in C++17, which came after this blog post was written. I agree, maybe if he had written it today his views would be different.
- dkrikun 8y agoWriting C++ like Java (or any other language for that matter) won't help anyone. The code will turn out non-idiomatic and weird for any couple of C++-eyeballs.
- pjmlp 8y agoI always find this comment funny, because C++ is older than Java and many Java programming patterns originated from C++ designs. Then again, many C++ younger devs don't even know what Booch method might be all about.
- dkrikun 8y agoThey have originated from C++, fine, but it is a different language, different ecosystem, different community, different ideology and -- different idioms
- Nimelrian 8y agoEspecially since the GoF Design Patterns, which are often cited as the main reason for Java being verbose, were described in the original book using C++ (and smalltalk) examples. Just because they may be overused in Java doesn't mean people shouldn't use them at all in other languages.
- jayd16 8y agoThis is a classic design pattern. Its not language specific.
- mdpopescu 8y agoMake constructors private and use (static) factory methods with meaningful names is underused, IMO.
- JoshuaAshton 8y agoThis forces you to allocate it on the heap... The C init function didn't require this.
- kllrnohj 8y agoHave it return by value in an optional then if that's what you want. You're not forced to do it on the heap. Or if for some reason you need to be able to pick you can do the whole templated allocator song & dance.
- deleted 8y ago[deleted]