I have a 3rd party (logging) class that overloads the << operator. The client code using this logger class can use this by calling one of the pre-defined macros. As an example:
//logs can be filtered based on this module id string
LOGGER_INFO("MODULE_ID_STR") << "Logging at info level";
I'd like to extend this feature wherein the class/module using this 3rd party logger does not have to include the module id string each time. Meaning - the client code should set the module id string once and then be able to do this:
cLogger.INFO << "Logging at info level";
The above call should internally use the registered module id string registered earlier and then use that to make the actual 3rd party log call. So can this be done elegantly in C++ by overloading the << operator for each of the log levels.
Some additional details...I started out by doing this:
This is the class that extends the functionality of the 3rd party logger:
class LoggerEx
{
public:
LoggerEx(const std::string &moduleToLog)
{
m_ModuleID = moduleToLog;
};
virtual ~LoggerEx() {};
class Debug
{
//overload the << operator (how to write this..??)
LOGGER_INFO(m_ModuleID) << "Logging at info level";
};
class Info
{
//overload the << operator
};
//Note that there could be more such levels
// (INFO, WARN, ERROR, TRACE, FATAL, etc).
public:
Debug DEBUG;
Info INFO;
protected:
std::string m_ModuleID
};
Some client code using the logger class should be allowed to do this...
class Xyz
{
public:
Xyz() : l("Xyz")
{}
void doSomething()
{
l.DEBUG << "Doing something";
}
protected:
Logger l;
};
Another client class...
class Mno
{
public:
Xyz() : l("Mno")
{}
void processSomething()
{
l.INFO << "Process something";
}
protected:
Logger l;
};
Since the original logger supports several data types (int, float, chars, std::string), will the above be the approach, or are there any other ideas/solutions to do this more elegantly in C++ without writing a full blown wrapper (or duplicating code) to the logger?
Thanks...
This is actually harder than one might think, mostly because in a typical logging library, the LOGGER_INFO macro or its equivalents do more than just giving you a stream. Here's a typical macro from Boost:
#define BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, rec_var, params_seq)\
for (::boost::log::record rec_var = (logger).open_record((BOOST_PP_SEQ_ENUM(params_seq))); !!rec_var;)\
::boost::log::aux::make_record_pump((logger), rec_var).stream()
A quick look at this code shows that it creates a new record, creates a pump, gets the stream from this pump, and your << "log text here" << " more log stuff" calls actually operates on that stream. It is when the pump and record gets destructed, at the end of the statement, that the message actually get pushed out into a single log entry, which makes sense when you think of it - you'd expect LOGGER_INFO(m_ModuleID) << "Logging at info level" << "more text"; to produce one log entry instead of two.
Thus a naive implementation like
class LoggerEx
{
public:
LoggerEx(const std::string &moduleToLog) : Debug(moduleToLog)
{ }
~LoggerEx() {}
class Debug
{
private:
std::string m_ModuleID;
public:
Debug(const std::string &module) : m_ModuleID(module) {}
template <typename T>
const Debug & operator << (const T& thing_to_log) const {
LOGGER_INFO(m_ModuleID) << thing_to_log;
return *this;
}
};
public:
Debug DEBUG;
};
will only work if you only use << once per statement in your logging code.
One possible way of getting around it would be to use an internal stream to store the log-entry-in-making:
class LoggerEx
{
public:
LoggerEx(const std::string &moduleToLog) : m_module(moduleToLog)
{ }
~LoggerEx() {}
class Debug
{
private:
std::string m_ModuleID;
std::stringstream m_ss;
public:
Debug(const std::string &module) : m_ModuleID(module) {}
Debug(const Debug &other) : m_ModuleID(other.m_ModuleID) {}
~Debug() {
std::string str = m_ss.str();
if(!str.empty())
LOGGER_INFO(m_ModuleID) << str;
}
template <typename T>
Debug & operator << (const T& thing_to_log) {
m_ss << thing_to_log;
return *this;
}
};
public:
Debug DEBUG() { return Debug(m_module);}
private:
std::string m_module;
};
It would be called like
l.DEBUG() << "Some stuff " << some_number << " some more stuff";
The idea is that the DEBUG() call produces a temporary object; your operator << calls on that temporary object writes stuff into the stringstream, and at the end of the line, when the temporary object gets destructed, the things in the stringstream get pushed out to the logging library.
Related
I want to write a program and enable the user to have control over the logging of the package by setting the program to display progress or disable that.
I know that std::cout is an std::ostream with the difference that std::cout redirects the results to standard output.
I want my class to have an std::ostream member that I log everything to. Then if the user enables display, that member will be attached to std::cout and displays the results, otherwise it wont.
What I have in mind is something similar to this:
class log {
private:
std::ostream display;
public:
void func();
void show_display();
}
void log::func(){
display << "called by func";
}
void log::show_display(){
// redirect display to standard output
}
Is there any way similar to above to do this? If not, how can I have similar results?
Thanks.
Stream handles aren't copyable objects, nor are there any std::ostream objects that you the user can instantiate. So your class as written cannot work. What you could do instead is store a pointer:
#include <iostream>
class log {
std::ostream* out_;
public:
void func() {
if (out) { *out << "called by func"; }
// ...
}
void show_display() {
out = &std::cout;
}
void hide_display() {
out = nullptr;
}
};
If you plan to build a more general-purpose logging system, you should consider whether logging to a disabled output requires evaluation of operands; users may expect that a log statement such as log << expensive_function(); is cheap when the logging is disabled.
C++ has limited ability to use pointer-to-member functions. I need something that will allow me to dynamically choose a callback member function, in order to use the Visitor pattern of the XMLNode::Accept(XMLVisitor *visitor) method from the TinyXML2 library.
To use XMLNode::Accept(), I must call it with a class which implements the XMLVisitor interface. Hence:
typedef bool (*Callback)(string, string);
class MyVisitor : public tinyxml2::XMLVisitor {
public:
bool VisitExit(const tinyxml2::XMLElement &e) {
callback(e.Name(), e.GetText());
}
Callback callback;
}
This works fine if my caller is NOT an object which wants to use one of its own methods as a callback function (so that it can access class variables). For example, this works:
bool myCallBackFunc(string e, string v) {
cout << "Element " << e << " has value " << v << endl;
return true;
}
int main(...) {
tinyxml2::XMLDocument doc;
doc.LoadFile("somefile.xml");
MyVisitor visit;
visit.callback = myCallBackFunc;
doc.Accept(&visit);
}
However, in my use case, the parsing is done inside a method in a class. I have multiple applications which have similar but unique such classes. I'd like to use only one generic MyVisitor class, rather than have the visitor class have unique knowledge of the internals of each class which will call it.
Thus, it would be convenient if the callback function were a method in each calling class so that I can affect the internal state of the object instantiated from that calling class.
Top level: I have 5 server applications which talk to 5 different trading partners, who all send XML responses, but each is enough different that each server app has a class which is unique to that trading partner. I'm trying to follow good OO and DRY design, and avoid extra classes having unique knowledge while still doing basically the same work.
Here's the class method I want Accept() to call back.
ServiceClass::changeState(string elem, string value) {
// Logic which sets member vars based on element found and its value.
}
Here's the class method which will call Accept() to walk the XML:
ServiceClass::processResponse(string xml) {
// Parse XML and do something only if certain elements present.
tinyxml2::XMLDocument doc;
doc.Parse(xml.c_str(), xml.length());
MyVisitor visit;
visit.callback = &changeState; // ERROR. Does not work.
visit.callback = &ServiceClass::changeState; // ERROR. Does not work.
doc.Accept(&visit);
}
What's a simple way to get what I want? I can imagine more classes with derived classes unique to each situation, but that seems extremely verbose and clumsy.
Note: In the interest of brevity, my sample code above has no error checking, no null checking and may even have minor errors (e.g. treating const char * as a string ;-).
Below is the std::bind(..) example for what you're trying to do in C++11. For earlier C++ versions you could use the boost::bind utilities.
Fix your MyVisitor::VisitExit(...) method to return a boolean, by the way.
The code is converting const char * to std::string. tinyxml2 does not guarantee that the char * arguments from Name() or GetText() are not null. In fact in my experience they will be null at some point. You should guard against this. For the sake of not modifying your example too much I've not protected against this possibility everywhere in the example.
typedef bool(*Callback)(string, string);
using namespace std;
class MyVisitor : public tinyxml2::XMLVisitor {
public:
bool VisitExit(const tinyxml2::XMLElement &e) {
// return callback(e.Name(), e.GetText());
return true;
}
Callback callback;
};
/** Typedef to hopefully save on confusing syntax later */
typedef std::function< bool(const char * element_name, const char * element_text) > visitor_fn;
class MyBoundVisitor : public tinyxml2::XMLVisitor {
public:
MyBoundVisitor(visitor_fn fn) : callback(fn) {}
bool VisitExit(const tinyxml2::XMLElement &e) {
return callback(e.Name() == nullptr ? "\0" : e.Name(), e.GetText() == nullptr ? "\0": e.GetText());
}
visitor_fn callback;
};
bool
myCallBackFunc(string e, string v) {
cout << "Element " << e << " has value " << v << endl;
return true;
}
int
main()
{
tinyxml2::XMLDocument doc;
doc.LoadFile("somefile.xml");
MyVisitor visit;
visit.callback = myCallBackFunc;
doc.Accept(&visit);
visitor_fn fn = myCallBackFunc; // copy your function pointer into the std::function<> type
MyBoundVisitor visit2(fn); // note: declare this outside the Accept(..) , do not use a temporary
doc.Accept(&visit2);
}
So from within the ServiceClass method you'd do:
ServiceClass::processResponse(string xml) {
// Parse XML and do something only if certain elements present.
tinyxml2::XMLDocument doc;
doc.Parse(xml.c_str(), xml.length());
// presuming changeState(const char *, const char *) here
visitor_fn fn = std::bind(&ServiceClass::changeState,this,std::placeholders::_1,std::placeholders::_2);
MyBoundVisitor visit2(fn); // the method pointer is in the fn argument, together with the instance (*this) it is a method for.
doc.Accept(&visit);
}
You can use generics in order to support whichever callback you'd like.
I've tried to mock the classes of the library in order to give you a fully runnable example:
#include <string>
#include <iostream>
#include <functional>
class XmlNode {
public:
XmlNode(const std::string& n, const std::string t) : name(n), txt(t) {}
const std::string& Name() const { return name; }
const std::string& GetText() const { return txt; }
private:
std::string name;
std::string txt;
};
class XMLVisitor {
public:
virtual void VisitExit(const XmlNode& node) = 0;
virtual ~XMLVisitor() {}
};
template<typename T>
class MyVisitor : XMLVisitor {
public:
MyVisitor() {}
void myInnerPrint(const XmlNode& node) {
std::cout << "MyVisitor::myInnerPrint" << std::endl;
std::cout << "node.Name(): " << node.Name() << std::endl;
std::cout << "node.GetText(): " << node.GetText() << std::endl;
}
void SetCallback(T newCallback) {
callback = newCallback;
}
virtual void VisitExit(const XmlNode& node) {
callback(node);
}
T callback;
};
int main() {
XmlNode node("In", "Member");
MyVisitor<std::function<void(const XmlNode&)>> myVisitor;
auto boundCall =
[&myVisitor](const XmlNode& node) -> void {
myVisitor.myInnerPrint(node);
};
myVisitor.SetCallback(boundCall);
myVisitor.VisitExit(node);
return 0;
}
First define a template and a helper function:
namespace detail {
template<typename F>
struct xml_visitor : tinyxml2::XMLVisitor {
xml_visitor(F&& f) : f_(std::move(f)) {}
virtual void VisitExit(const tinyxml2::XMLElement &e) {
f_(e);
}
private:
F f_;
};
}
template<class F>
auto make_xml_visitor(F&& f)
{
return detail::xml_visitor<std::decay_t<F>>(std::forward<F>(f));
}
Then use the helper function to construct a custom visitor from a lambda which captures this:
void ServiceClass::processResponse(std::string xml) {
// Parse XML and do something only if certain elements present.
tinyxml2::XMLDocument doc;
doc.Parse(xml.c_str(), xml.length());
auto visit = make_xml_visitor([this](const auto& elem)
{
this->changeState(elem.Name(), elem.GetText);
});
doc.Accept(std::addressof(visit));
}
The rule is that a function pointer must always accept a void * which is passed in to the module which calls it, and passed back. Or use a lambda which is the same thing with some of the machinery automated for you. (The void * is the "closure").
So
typedef bool (*Callback)(string, string, void *context);
class MyVisitor : public tinyxml2::XMLVisitor {
public:
bool VisitExit(const tinyxml2::XMLElement &e) {
callback(e.Name(), e.GetText(), contextptr);
}
Callback callback;
void *contextptr;
}
bool myCallBackFunc(string e, string v, void *context) {
ServiceClass *service = (ServiceClass *) context;
cout << "Element " << e << " has value " << v << endl;
service->ChangeState(e, v);
return true;
}
I have a simple GUI program that uses a custom stringstream to redirect output from the console to a text field in the GUI (under some circumstances). currently. the window redraws any time I hit enter, but it's possible that output could be generated at other times. Is there a way to register a function with the stringstream that gets executed every time the << operator is used on the stream?
NOTE
I should have pointed out that I cannot use C++11 in my solution. the machines on which this will be compiled and run will not have c++11 available.
Personally, I wouldn't use an std::ostringstream (or even an std::stringstream) for this at all! Instead, I would create my own stream buffer taking care of sending the data to the GUI. That is, I'd overwrite std::streambuf::overflow() and std::streambuf::sync() to send the current data to the GUI. To also make sure that any output is sent immediately, I'd set up an std::ostream to have std::ios_base::unitbuf set. Actually, sending the changes to a function is quite simple, i.e., I'll implement this:
#include <streambuf>
#include <ostream>
#include <functional>
#include <string>
#include <memory>
#include <iostream> // only for testing...
#if HAS_FUNCTION
typedef std::function<void(std::string)> function_type;
#else
class function_type
{
private:
struct base {
virtual ~base() {}
virtual base* clone() const = 0;
virtual void call(std::string const&) = 0;
};
template <typename Function>
struct concrete
: base {
Function d_function;
concrete(Function function)
: d_function(function) {
}
base* clone() const { return new concrete<Function>(this->d_function); }
void call(std::string const& value) { this->d_function(value); }
};
std::auto_ptr<base> d_function;
public:
template <typename Function>
function_type(Function function)
: d_function(new concrete<Function>(function)) {
}
function_type(function_type const& other)
: d_function(other.d_function->clone()) {
}
function_type& operator= (function_type other) {
this->swap(other);
return *this;
}
~function_type() {}
void swap(function_type& other) {
std::swap(this->d_function, other.d_function);
}
void operator()(std::string const& value) {
this->d_function->call(value);
}
};
#endif
class functionbuf
: public std::streambuf {
private:
typedef std::streambuf::traits_type traits_type;
function_type d_function;
char d_buffer[1024];
int overflow(int c) {
if (!traits_type::eq_int_type(c, traits_type::eof())) {
*this->pptr() = traits_type::to_char_type(c);
this->pbump(1);
}
return this->sync()? traits_type::not_eof(c): traits_type::eof();
}
int sync() {
if (this->pbase() != this->pptr()) {
this->d_function(std::string(this->pbase(), this->pptr()));
this->setp(this->pbase(), this->epptr());
}
return 0;
}
public:
functionbuf(function_type const& function)
: d_function(function) {
this->setp(this->d_buffer, this->d_buffer + sizeof(this->d_buffer) - 1);
}
};
class ofunctionstream
: private virtual functionbuf
, public std::ostream {
public:
ofunctionstream(function_type const& function)
: functionbuf(function)
, std::ostream(static_cast<std::streambuf*>(this)) {
this->flags(std::ios_base::unitbuf);
}
};
void some_function(std::string const& value) {
std::cout << "some_function(" << value << ")\n";
}
int main() {
ofunctionstream out(&some_function);
out << "hello" << ',' << " world: " << 42 << "\n";
out << std::nounitbuf << "not" << " as " << "many" << " calls\n" << std::flush;
}
A fair chunk of the above code is actually unrelated to the task at hand: it implements a primitive version of std::function<void(std::string)> in case C++2011 can't be used.
If you don't want quite as many calls, you can turn off std::ios_base::unitbuf and only sent the data upon flushing the stream, e.g. using std::flush (yes, I know about std::endl but it unfortunately is typically misused to I strongly recommend to get rid of it and use std::flush where a flush is really meant).
In order to do this you should create your own streambuf class. streambuf classes represent IO devices and each one takes care of the various issues specific to that kind of device. The standard defines a streambuf for files and another for strings. Network access would use another, and output to a GUI should also be represented as another kind of device if you're going to use streams at all.
Writing an appropriate streambuf class isn't trivial and seems to be kind obscure, but there are resources out there. The C++ Standard Library - A Tutorial and Reference has a small section on this. Standard C++ IOStreams and Locales: Advanced Programmer's Guide and Reference provides in-depth information. A search for subclassing basic_streambuf will also turn up some free resources online.
If you haven't already, can you derive a subclass from stringstream and overload its stream insertion operator to generate events?
Pseudocode:
class AlertingStream : public stringstream
{
ostream& operator << (type)
{
for (each listener in listeners)
{
listener.notify();
}
perform insertion;
return *this;
}
}
I'm making a logger and I wish to have some kind of stream-like happenings going on, ideally doing CLogger << "Testing, " << 1 << ",2,3\n"; instead of CLogger->log("Testing, %i,2,3", 1);
My question is how would I do this? I don't want to directly create a stream to stdout as I want to use my own method which includes writing files and such. I've considered overloading with a certain struct that'd flush the current stream buffer to a method, but I'd have to do CLogger << flush << "Test!\n"; which is kind of odd.
Does anybody know how to do this?
If all that you need is directing certain log messages to files, have you considered std::ofstream?
Otherwise, I like to derive my logging class from std::ostream, so I get all of the stream goodness. The trick is to put all of your application-specific code in the associated streambuf class. Consider:
#include <iostream>
#include <sstream>
class CLogger : public std::ostream {
private:
class CLogBuf : public std::stringbuf {
private:
// or whatever you need for your application
std::string m_marker;
public:
CLogBuf(const std::string& marker) : m_marker(marker) { }
~CLogBuf() { pubsync(); }
int sync() {
std::cout << m_marker << ": " << str();
str("");
return std::cout?0:-1;
}
};
public:
// Other constructors could specify filename, etc
// just remember to pass whatever you need to CLogBuf
CLogger(const std::string& marker) : std::ostream(new CLogBuf(marker)) {}
~CLogger() { delete rdbuf(); }
};
int main()
{
CLogger hi("hello");
CLogger bye("goodbye");
hi << "hello, world" << std::endl;
hi << "Oops, forgot to flush.\n";
bye << "goodbye, cruel world\n" << std::flush;
bye << "Cough, cough.\n";
}
Notes:
The CLogger constructor can take whatever parameters you need to use -- a filename, an output language, a pointer to the underlying log data, whatever. Just pass the data onto the CLogBuf class.
The CLogBuf's sync() is automatically called during in response to std::flush.
Check out operator <<, which is what STL's streams overload.
class CLogger
{
public:
CLogger& operator << (const std::string& _rhs)
{
// work with it here
return *this;
}; // eo operator <<
}; // eo class CLogger
EDIT:
See this page that outlines how std::ostream overloads operator << for different types:
http://www.cplusplus.com/reference/iostream/ostream/operator%3C%3C/
Implement a proxy object that gives you operator<< and pass an ownership marker to the returned proxy object. When an object with the ownership marker dies, you flush the stream.
An easy way to do this would be to wrap ostringstream in an auto_ptr in your proxy and flushing to your logger when the auto_ptr is not null in the proxy's d-tor.
That'll give you the formatting possible with ostream, but still result in only one call to your logger, which I thought was the real problem.
Think of something like this:
class CLoggingProxy
{
public:
template <class T>
CLoggingProxy operator<<( const T& rhs )
{
if ( stream )
*stream << rhs;
return *this;
}
~CLoggingProxy()
{
if ( stream )
logger->log(stream->str());
}
private:
std::auto_ptr<std::ostringstream> stream;
CLogger* logger;
friend class CLogger;
CLoggingProxy( CLogger* logger ) // call this e.g. from the logger to "start" input
: stream(new std::ostringstream), logger(logger) {}
};
All of the operator<<() functions are defined on the class ostream, which you can inherit from and implement its methods.
I'm just going to copy-paste my current implementation of this below, it does all you need (and handles things like std::endl and the like). AMBROSIA_DEBUGis macro defined in debug builds, so in theory, every call to this output class should be omitted in release builds (haven't checked though, but seems logical overhead is kept to a minimum. The functionality is based on QDebug functionality, plus a little addition of mine debugLevel, which would allow you to filter debug messages by hand in your code depending on a runtime parameter. Right now it also adds the same amount of spaces before each message.
// C++ includes
#include <iostream>
#include <string>
typedef std::ostream& (*STRFUNC)(std::ostream&);
#ifdef AMBROSIA_DEBUG
static int debugLevel;
const static int maxDebugLevel = 9;
#endif
class Debug
{
public:
#ifdef AMBROSIA_DEBUG
Debug( const int level = 0 )
: m_output( level <= debugLevel ),
m_outputSpaces( true ),
m_spaces( std::string(level, ' ') )
#else
Debug( const int )
#endif // AMBROSIA_DEBUG
{}
template<typename T>
#ifdef AMBROSIA_DEBUG
Debug& operator<<( const T &output )
{
if( m_output )
{
if( m_outputSpaces )
{
m_outputSpaces = false;
std::cerr << m_spaces;
}
std::cerr << output;
}
#else
Debug& operator<<( const T & )
{
#endif // AMBROSIA_DEBUG
return *this;
}
// for std::endl and other manipulators
typedef std::ostream& (*STRFUNC)(std::ostream&);
#ifdef AMBROSIA_DEBUG
Debug& operator<<( STRFUNC func )
{
if( m_output )
func(std::cerr);
#else
Debug& operator<<( STRFUNC )
{
#endif // AMBROSIA_DEBUG
return *this;
}
private:
#ifdef AMBROSIA_DEBUG
bool m_output;
bool m_outputSpaces;
std::string m_spaces;
#endif // AMBROSIA_DEBUG
};
Example usage:
int main()
{
debugLevel = 9; // highest allowed in my app...
Debug(4) << "This message should have an indentation of 4 spaces." << endl;
Debug(8) << "This is a level 8 debug message.\n";
return 0;
}
a bit of a vague question but I am looking for pointers as to how can I generate String diff vectors in C++. The scenario is such that given a paragraph I want to store the various differences(Edit, cut copy paste etc.) it goes through in a draft mode to review Audit history.
Any hints in this regard will be really appreciated.
An idea using C++ polymorphism:
class Action
{
public:
virtual void revert(std::string& base) = 0;
};
class InsertAction : public Action
{
private:
int pos, len;
public:
InsertAction(int pos, std::string& base, const std::string& in) : len(in.size()), pos(pos)
{
base.insert(pos, in);
}
virtual void revert(std::string& base)
{
base.erase(pos,len);
}
};
int main()
{
std::string text("hello !");
std::cout << text << std::endl;
Action* action = new InsertAction(5, text, " world");
std::cout << text << std::endl;
action->revert(text);
std::cout << text << std::endl;
delete action;
}
You can then add and pop Actions from a LIFO queue as you want. It's a simple example, you could also try to link it more to a string instead of always passing at as a param, but that's up to your own design. I know it's not 'real' diffing, but I think this solution to be closer coupled to the problem then really storing general string differences.