Handling errors elegantly is something C++ was missing for a long time.
In the early days, we used a lot of techniques, such as returning HRESULT (...
For further actions, you may consider blocking this person and/or reporting abuse
That's a good option for functions that would not return anything real, except a success indication. For other functions I really like to use std::optional to handle possible failures. This does not offer a way to tell the caller what went wrong, but there a lots of situations where that is not necessary.
Some may argue for throw .. catch and exception handling as a way for error handling, but my point of view is :
for functions which have equal chance of failure as success, exception handling is not the way to go
throw catch exception should not be used as a replacement to the regular error handling. In the below presentation Bjarne describes rules for using error-codes and exceptions he is following:
youtu.be/VoHOLDdfDhk?t=2714