I need to monitor my functions for "errors" and want to print the warnings at the end of the functions. I thought using singleton class could be a good idea in here (code inspired by this example):
class Warning { bool status; std::string message; static Warning *global_warning_ptr; Warning() { defaults(); } public: void defaults() { message = "no warnings"; status = false; } void set(std::string v) { message = v; status = true; } void print() { if (status) { std::cout << message std::endl; defaults(); } } static Warning *msg() { if (!global_warning_ptr) global_warning_ptr = new Warning; return global_warning_ptr; } }; Warning *Warning::global_warning_ptr; that is used by multiple functions as below
void bar(double x) { if (x < 0) Warning::msg()->set("Wrong values"); } void foo(std::vector x) { int n = x.size(); for (int i = 0; i < n; i++) { bar(x[i]); } Warning::msg()->print(); // print single warning if any error occures } However using singletons is often considered as a bad coding practice. Is there any better alternative or place for improvment in my code? Is there anything I should worry about when using it?
msg()function has a race condition. If you are out of memory (unlikely maybe), you could have fun effects, too. Also, in a chain of errors (error causes another error), you only see the (least interesting) last warning but not those leading to it. If you program embedded code without exceptions, I thinkbool Foo(double x) ...and error checks along the call path is superior. If you use exceptions, then simply throw and catch where convenient. Functions which "warn" about invalid arguments will most likely bail anyway. \$\endgroup\$footwice, where only the first call fails, still causes both calls to print a warning, because you forgot to explicitly reset the global warning instance. If later it turns out thatfooneeds to call another method after callingbar, and that method also sets a warning, then anybarwarning message is lost. Why don't you letbarreturn an error code, sofoocan check it and log a warning for eachbarcall that fails (or a general warning if any call failed, depending on your needs)? \$\endgroup\$