I found a new way to do it. It is non-standard and this is an entirely new way to do it.
So consider using this approach cautiously.
Use the following header file: 
SetError.h:
#include <string> // for string class 
#ifndef SET_ERROR_IS_DEFINED
#define SET_ERROR_IS_DEFINED
class Error {
public:
    int code = 0;
    std::string errorMessage;
    std::string fileName;
    std::string functionName;
    Error() {}
    Error(int _errorCode, std::string _functionName = "", std::string _errorMessage = "", std::string _fileName = "")
    {
        code = _errorCode;
        functionName = _functionName;
        errorMessage = _errorMessage;
        fileName = _fileName;
    }
};
#if defined(_DEBUG) || !defined(NDEBUG) 
#define ___try { _ERROR.code = 0; bool __valid_try_mode_declared; 
#define ___success }
#define SetError(pErrorData) __valid_try_mode_declared = true; _ERROR = *pErrorData; delete pErrorData;
#else
#define ___try { _ERROR.code = 0;
#define ___success }
#define SetError(pErrorData) _ERROR = *pErrorData; delete pErrorData; 
#endif
#endif
inline Error _ERROR;
Include it everyware.
Example of how to use:
Main.cpp:
#include "SetError.h"
#include <iostream>
bool SomeFunction(int value) ___try; 
{ 
    if (value < 0) {
        SetError(new Error(10, "SomeFunction", "Some error", "File main.cpp"));
        return false;
    }
    return true;
} ___success; // You mast to warp the function with both ___try and ___success
// These keywords must be at the start and the end of the function!
int main()
{
    using namespace std;
    bool output = SomeFunction(-1);
    if (_ERROR.code != 0) { // This is how you check the error code. using the global _ERROR object
        cout << "error code: " << _ERROR.code << ", from function: " 
            << _ERROR.functionName << ", from file: " << _ERROR.fileName;
    }
    cout << endl << "Founction returned: " << output << endl;
    return 1;
}
If you have some functions that run in another thread, these functions need to be inside namespace and then you can do this:
namespace FunctionsInSomeThread
{
    #include "SetError.h"
    bool SomeFunc1() ___try;
    {
        SetError(new Error(5, "SomeFunction2", "Some error from another thread", "File main.cpp"))
        return true;
    } ___success;
    bool SomeFunc2() ___try;
    {
        SetError(new Error(5, "SomeFunction2", "Some error from another thread", "File main.cpp"))
            return true;
    } ___success;
}
And to access _Error, you need to add the namespace of the thread
if (FunctionsInSomeThread::_ERROR.code != 0)
{
    // Error handling
}
Or in case it is inside the same namespace then no need to add FunctionsInSomeThread:: before.
The idea behind this is that you can't warp the function only with ___success; keyword. You will get compile error. So the developer will never return old error code from another function.
If you wrote ___success; at the end of the codeblock, you must write also ___try; at the start!
You also can't use SetError macro if it is not wrapped in ___try; and ___success;.
The idea come from the AutoIt language where you have this consept:
https://www.autoitscript.com/autoit3/docs/functions/SetError.htm
So this is almost the same in C if you use this header.