This article can be seen as a very good explanation of why exceptions are a valuable feature for a language. In python, mentioning one of the languages exposed in the article, I would return the created object and throw an exception on error.
I'm personally fond of filling an error buffer, but a bit more explicitly than just an int.<p><pre><code> typedef struct APIError {
int code;
char *description;
};
/**
* Returns NULL and fills the error parameter if creation was unsuccessful.
*/
Something APICreateSomething(bool param1, int param2, APIError *error);
</code></pre>
So common execution would be:<p><pre><code> APIError error;
Something something = APICreateSomething(true, 3, &error);
if (error) {
// handle error...
}
</code></pre>
And if the user passed in NULL for the error parameter, then that's their problem, and they won't get error information.
I think something that he has missed is the design of passing functions as params for success and failures.
Of course these are generally used when there are external API calls which are async, but nowadays those kind of API calls are quite common.<p>void createSomething(bool param1,int param2, Something something, success: function (something) {}, error: function (error){});<p>Of course this would be in those languages that support passing of functions as params.
One of the unmentioned advantages of style "A", passing in a pointer to where you want the result, is that the caller can trivially switch allocators if they need that speed (e.g. a specialized slab allocator is much faster than malloc). If you want to support this with the other styles, you end up adding a parameter (or generic parameter) for the allocator.<p>Style "E" is also known as an error monad, and has a lot of advantages when writing functional-style code. For example, you can use the usual List.map on a function that returns an error monad but not on one that has out parameters or throws exceptions.
I checked out the LLVM source [0] and what they do is slightly different (their is a tagged union) since their HasError is not part of the union which makes more sense since it does not rely on memory alignment. It does not really matter since it seems that the values in the struct are aligned appropriately anyway but it'd still be pretty wonky if there was just the union.<p>[0] <a href="https://github.com/llvm-mirror/llvm/blob/eee7a7a8362afddab3fd9bf10b7023da7e7c42e5/include/llvm/Support/ErrorOr.h#L265" rel="nofollow">https://github.com/llvm-mirror/llvm/blob/eee7a7a8362afddab3f...</a>
I really enjoyed this article. I think I personally prefer the struct return. It's explicit, if maybe a tiny bit wasteful of memory. Certainly there will be people whom this affects, but I think its good overall.
With tuples in C++11 you can have multiple return values and ignore ones you don't want: <a href="http://ideone.com/3eHOld" rel="nofollow">http://ideone.com/3eHOld</a>