В коде LLVM применяют такой подход, про которых говорит Александр, может быть будет полезно, вот описание их класса
https://llvm.org/doxygen/classllvm_1_1Expected.html а вот - самого подхода For functions that can fail but need to return a value the Expected<T> utility can be used. Values of this type can be constructed with either a T, or an Error. Expected<T> values are also implicitly convertible to boolean, but with the opposite convention to Error: true for success, false for error. If success, the T value can be accessed via the dereference operator. If failure, the Error value can be extracted using the takeError() method.
https://llvm.org/docs/ProgrammersManual.html#recoverable-errors