C++ DBJ Error Concept, at last

So little C++ so much good!

Caveat Emptor

This is left in here purely for historical reasons. This is probably the first coherent text of mine on the subject of valstat.

[2019-07-16]

Approximately 7 months ago I posted to Reddit. Under the title:

Decades have passed, standard C++ has no agreed and standard error handling concept.

That got attention of the crowd, and some important folks from the C+++ universe also chimed in. More or less all approving.

I obviously had to show some code. No pressure there.

14ned‘ (well known as Nial Douglas) was especially helpful, in that thread. This comment of his “sums it up” rather soberly I think:

“.. Zero overhead exceptions are not expected for C++ 23 currently, but rather as an experimental feature. If C adopts them for C23, then all the major compilers will have them, but they still wouldn’t enter until C++ 26 as for obvious reasons C++ 23 can’t incorporate C23..”

So, after decades of going in all directions at the same time, we are expected to wait  “just few more years” to have ISO C++ error concept.

I can not wait that much. I need to have concept, design and canonical implementations right now and right in the middle of several teams waiting. Or even worse inventing their own error concepts.

After months of cogitations, I have at last come out, with my “concept”. Sufficiently light and simple. Effective if used ubiquitously. Read on.

VALSTAT

Value & Status

(c) 2019 by dbj.org — CC BY-SA 4.0

Return handling paradigm shift

Three primary objectives

  1. Can not wait C++23 and P0709 realization
  2. Produce a simple, universally applicable solution, now.
  3. Achieve maximum with minimum

They are always coming as trios. After spending much more time than expected, in experimenting and testing, this is my architecture of the solution. With reasoning behind.

“Error Handling” becomes Light and Useful

Error (handling) was a wrong name. Not every return denotes an error. In this architecture, both value and status are potentially returned. The “and” is the key word. Not the “or”.

Here is the simple and standard C++ code, actually explaining it all.

Seems interesting. But what is the value of this? Here is the solution domain for the above:
Instant type to return optional value and optional status.

Not much is developed here, it is all just about using the std:: lib. Not much can go wrong.  Here is the simple usage with the “structured binding” core usage idioms.

An distillation of many weeks of work. Very simple and logical. No macros. Just standard C++.

Key concept is the AND word

Value AND Status

Recap. pair_of_options is the core data structure.

Four (4) possible states of “occupancy” of this structure are (a and b are instances of types T1 and T2):

Above are the four (4) possible states in which instance of the core structure can exist.

Thinking about and solving the architecture of return types, I have came to the conscious and key conceptual conclusion: value AND status, not value OR error.

Error is just one of the states (a condition) of the return event, at the consuming site.

Error is a misleading name here. Status is the right name for what might be returned, with optional value.

Both absence and presence, of both value and state, gives the logic, to be used by the consumers aka callers.

In the core structure, both Value and Status are optional. They might be or might not be present in the structure returned. For the consuming code, this renders four (4) possible states at the consuming site.

  1. FATAL
    1. If both value AND status are empty that is an fatal error
  2. INFO
    1. if both value AND status are not empty that is an info state.
  3. OK
    1. Just value is returned
  4. ERROR
    1. Just status is returned, there is no value.

Does this mean we have to check always, for all four when using this type returned? I think not.

FATAL state we might take care of checking in debug builds only. INFO, OK or ERROR consuming depends on the consumers logic; on the context. We do not have always to distinguish between all 4 possible states. It depends on the API delivering the valstat type.

As an example, consider consuming HTTP codes.

All the HTTP valstat results are made to be in the INFO state, both value and status are present as described by HTTP protocol

At debug time we might check if the implementer of http_get() has done that

I any of the cases above, status returned is expected and used. LOG is probably some macro using the syslog() behind.

Conclusion

All the similar solutions up till now are based on the “value OR error” concept,
most often implemented using the union type. Sometime using the discriminated union type, a.k.a variant.

I might be so bold to claim they are mostly over-engineered. In this instance, I do not implement things. I simply use the types from the std:: lib. It’s all there.

What about the current works?

I know about expected and outcome, etc. I might suggest if and when approaching them please do read first the “History” page. Nial is really great guy (never met him). I think his experiences written here are the most precious.

Outcome of the outcome V1 peer review, is the most telling part for me.

I aimed for valstat to fully conform to the point 1: Lightweight. Thus, at the valstat core there is no actual implementation. Just usage of the types available from the std:: lib of C++17.

Application

I have developed a valstat core , dealing with posix and WIN32 erros, inside my dbj++nanolib, then I expanded and used it in my minimal SQLITE3, C++ wrap up.

The code is not as simple as in this text, but the concept is exactly the same. I am hoping in future releases, I can make it much simpler. And present it.

I do hope the valstat solution for handling c++ returns, is recognized as simple enough to be used and resilient enough to be trusted.

Post Scriptum

There is no ideal solution. On the implementation level there can be a lot of options. All of them equally good. One can go ahead and implement a return mechism based on valstat to her liking. But stick to the valstat core concept, and  I can promise you, your C++ projects will be more consistent and most importantly inter-operable with others, following the same `valstat concept. At least on the level of error handling.

So little C++ so much good!
So little C++ so much good!