2

I am asking specifically for a C++ implementation. For example, let's say I have the following class:

class Worker{
        string worker_name;
        string worker_title;
    public:
        void setWorkerTitle(string title);
}

void Worker::setWorkerTitle(string title){
    if(title == "Employee" || title == "Boss"){
        worker_title = title;
        return;
    }
    else{
        cerr << "Error setting title for " << worker_name << endl;
        cerr << title << " is not a valid title." << endl;
        exit(1);
    }
}

In my main file, I have the following:

Worker worker1(name, title); // Assume the appropriate constructor exists
worker1.setWorkerTitle("This should fail");

Currently, the setWorkerTitle function will let the programmer know it failed to set the title of the worker named worker_name. This is useful enough, but is there a way I can add more information to this error to help the programmer find its exact location?

For example, it would be useful to print the line numbers in the program where the error occurred, similar to how a compiler will let you know every line in every file that led up to an error. Another option would be to print the name of the Worker object that caused the failure, not just the worker_name in the object.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
  • 1
    This is commonly called a stacktrace, which shows the path through code (with line numbers) to the error. Here's how to do it in C++ (assuming you are using GCC): http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes – Malcolm Crum May 14 '17 at 16:53
  • 1
    Or, more simply, you can use `__FILE__` and `__LINE__` in your error string - you can write a macro to wrap the logging statements like [this](https://stackoverflow.com/questions/13301428/token-pasting-and-line) – Useless May 14 '17 at 17:02
  • @Crummy Thanks! That was pretty close to what I wanted, although I'd prefer it to be a little more user-friendly (it seems like the function returns hex numbers). –  May 14 '17 at 17:24

1 Answers1

0

You could change Workers setWorkersTitle to return bool, and then use some custom macro:

#include <iostream>
#include <string>

using namespace std;

#define TEST_CALL(variableName, methodCall, message) do {if(!variableName.methodCall) \
std::cerr << "ERROR: Variable " #variableName " caused error in file " __FILE__ \
" at line " << __LINE__ << ", Error message: " message << std::endl; } while(0)

class Worker{
        string worker_name;
        string worker_title;
    public:
        bool setWorkerTitle(string title);
};

bool Worker::setWorkerTitle(string title){
    if(title == "Employee" || title == "Boss"){
        worker_title = title;
        return true;
    }
    else{
        return false;
    }
}

int main() {
    Worker worker1; // Assume the appropriate constructor exists
    TEST_CALL(worker1, setWorkerTitle("This should fail"), "incorret title");
}

The output is:

ERROR: Variable worker1 caused error in file main.cpp at line 29, Error message: incorret title

xinaiz
  • 7,744
  • 6
  • 34
  • 78
  • This is pretty close to what I'd like, but I'd prefer some more elegance if possible. I don't like the idea of having to call a macro to call my setter; this doesn't strike me as particularly user friendly. Writing __FILE__ and __LINE__ in the setter itself displays Worker.cpp as the filename and the line in Worker.cpp as the line, so is there a way to trace the file and line all the way back to its origin? –  May 14 '17 at 23:50
  • It is possible is you implement such functionality, but it won't be user friendly. C++ does not have reflection, so you would have to call some kind of macro in every line you want to be displayed in error message – xinaiz May 15 '17 at 10:46