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.
Related
I'd like to create a pipeline architecture constructed of plugins that ingest a variety of data types and can produce a variety of data types that would then be fed to any plugin connected to it. Since templated abstract functions aren't a thing, I figured what ever base class I used would need to define send and receive functions for all possible types. Child classes would then define receive functions for data types they are interested in, process the content, then send the newly generated data on to a vector of base classes via their receive functions. By default, the base class would just return on data types it hasn't specialized a receive function for, thus not doing anything (I understand there is probably unnecessary overhead here).
I failed to recall that calling a base's virtual function will invoke said base's version of the virtual function unless defined as pure virtual or the object I'm actually handling was that of the child. But since connected plugins would be stored in a vector of base plugins, all I would have had access to is the base's receive function. Turning the base's receive method into a pure virtual method would elevate the call to the child's receive method but that would mean I need to implement the entire possible interface for each plugin. Is there an easier way to doing this?
More general, is this a good approach to what I'm trying to do? This plugin pipeline would ideally be dynamic and created on demand so connecting plugins together in such a fashion seemed to be the right way to go. And it needs to be quick. If iterating over connected plugins to push data even when some plugins don't do anything with the data is slow, I can cache the data before pushing the reference on so I only iterate through the plugins once.
Guess this boils down to, is there a design architecture out there that allows for convenient communication between classes that supports a varying amount of transferable data types.
#define ADD_TYPE(type) \
inline void send(const routing::route_t route, const type& data) { for(auto &plugin : m_registered_plugins) plugin->receive(route, data); } \
virtual inline void receive(const routing::route_t& route, const type& data) { return; }
// Thought about trying this second -->
// virtual inline void receive(const routing::route_t& route, const type& data) = 0;
class PluginBase
{
public:
PluginBase(const std::string& name)
: m_uuid(m_uuid_gen())
, m_log(name)
{ }
virtual ~PluginBase() { }
bool pluginIsDescendant(PluginBase* plugin) const
{
for (auto registered : m_registered_plugins)
{
// Did we find the plugin
if (registered == plugin)
return true;
// Is the plugin a descendant of this
if (registered->pluginIsDescendant(plugin))
return true;
}
return false;
}
bool connect(PluginBase* plugin)
{
// Don't connect to self
if (plugin == this)
{
m_log.error("Cannot connect plugin to self!");
return false;
}
// Check for recursion
if (plugin->pluginIsDescendant(this))
{
m_log.error("Cannot connect! Plugin recursion detected.");
return false;
}
// Check if it already exists in the forward pipeline
if (pluginIsDescendant(plugin))
m_log.warning("Plugin already connected as descendant.");
m_registered_plugins.push_back(plugin);
return true;
}
ADD_TYPE(int);
ADD_TYPE(std::string);
ADD_TYPE(float);
protected:
// Logger
logger::Log m_log;
private:
// Static boost generator
static boost::uuids::random_generator m_uuid_gen;
// UUID of plugin
boost::uuids::uuid m_uuid;
// Vector of registered analytics
std::vector<PluginBase*> m_registered_plugins;
};
// EXAMPLE number CHILD CLASS
class NumberClass: public PluginBase
{
public:
void receive(const routing::route_t& route, const int value)
{
int output= transform(route, value);
send(route, output);
}
void receive(const routing::route_t& route, const float value)
{
float output= transform(route, value);
send(route, output);
}
};
// EXAMPLE std::string CHILD CLASS
class StringClass : public PluginBase
{
public:
void receive(const routing::route_t& route, const std::string value)
{
std::string output= transform(route, value);
send(route, output);
}
};
// EXAMPLE print CHILD CLASS
class PrintClass : public PluginBase
{
public:
void receive(const routing::route_t& route, const int value)
{
std::cout << "Route " << route << " sent int = " << value << std::endl;
}
void receive(const routing::route_t& route, const std::string value)
{
std::cout << "Route " << route << " sent string = " << value << std::endl;
}
};
int main()
{
NumberClass c1;
StringClass c2;
NumberClass c3;
PrintClass c4;
c1.connect(c4);
c2.connect(c4);
c3.connect(c4);
c1.receive(1, 10);
c2.receive(2, "hello");
c3.receive(3, 3.1415);
};
Expected:
Route 1 sent int = 10
Route 2 sent string = hello
Nothing is shown for the float 3.1415 because PrintClass never implemented the receive for float.
I am writing some classes in C++ to act as a personal small library and I encountered a problem.
Some of my objects make us of third-party libraries written in magnificent C style.
That means those libraries have functions like apiInit() and apiCleanup(), where the former must be called before any of the actual api functions and the latter must be called when you are not going to use them anymore.
What I want is to provide the classes that need a library with an access point to its functions ensuring apiInit() is called when the first needing class is created, or at least before any api function is used, and apiCleanup() is called when the last instance that uses the api is destroyed.
Keep in mind there are more than one class that makes use of a single library.
I could come with two solutions:
First, the obvious one, make the provider a singleton:
#include <iostream>
using namespace std;
class ContextProvider {
ContextProvider() {
cout << "Initializing API" << endl;
}
ContextProvider(ContextProvider const& rhs) = delete;
ContextProvider& operator=(ContextProvider const& rhs) = delete;
public:
~ContextProvider() {
cout << "Cleaning API" << endl;
}
static ContextProvider& getInstance() {
static ContextProvider instance;
return instance;
}
void useContext() {
cout << "Using API" << endl;
}
};
class ContextUser1 {
public:
ContextUser1() {
}
void doSomething() {
ContextProvider::getInstance().useContext();
}
};
class ContextUser2 {
public:
ContextUser2() {
}
void doSomethingElse() {
ContextProvider::getInstance().useContext();
}
};
The other one would be to keep a counter of context users, like so:
#include <iostream>
using namespace std;
class ContextProvider {
static unsigned int userCounter;
public:
ContextProvider() {
if (userCounter == 0)
cout << "Initializing API" << endl;
++userCounter;
}
~ContextProvider() {
--userCounter;
if (userCounter == 0)
cout << "Cleaning API" << endl;
}
void useContext() {
cout << "Using API" << endl;
}
};
unsigned int ContextProvider::userCounter = 0;
class ContextUser1 {
ContextProvider cp;
public:
ContextUser1() {
cp = ContextProvider();
}
void doSomething() {
cp.useContext();
}
};
class ContextUser2 {
ContextProvider cp;
public:
ContextUser2() {
cp = ContextProvider();
}
void doSomethingElse() {
cp.useContext();
}
};
int main() {
ContextUser1 cu11, cu12, cu13;
ContextUser2 cu21, cu22;
cu11.doSomething();
cu12.doSomething();
cu21.doSomethingElse();
cu22.doSomethingElse();
cu13.doSomething();
}
Both, when executed with the following main()
int main() {
ContextUser1 cu11, cu12, cu13;
ContextUser2 cu21, cu22;
cu11.doSomething();
cu12.doSomething();
cu21.doSomethingElse();
cu22.doSomethingElse();
cu13.doSomething();
}
yeld the expected result, that is:
Initializing API
Using API
Using API
Using API
Using API
Using API
Cleaning API
Now the obvious question is, which one is better, or which one should I use?
For example, some things that come to mind are...
Singleton method:
Advantages:
No need to store any counter.
No need to store any instance.
Disadvantages:
Syntaxis gets weird (ContextProvider::getInstance().use()).
It is a singleton, with all it's flaws.
Counter method:
Advantages:
The usage is straightfowrard.
The syntaxis is nice and clear (cp.use()).
Disadvantages:
Has to keep a counter of the number of users.
User classes have to store an instance of the ContextProvider class.
I mainly ask this question because I don't know which of these advantages/disadvantages weight more, if there are things I didn't account for, or maybe there is an obvious third method I couldn't come up with that is inherently better than those two, or, who knows.
Thank you for your time!
I'd use your second approach, with the following modifications:
class ContextUser1 {
std::shared_ptr<ContextProvider> cp;
public:
ContextUser1(const std::shared_ptr<ContextProvider>& cp)
: cp(cp) {
}
void doSomething() {
cp->useContext();
}
};
Making the dependency explicit makes your code better in terms of being testable. Also, using shared_ptr takes care of counting, so you don't even need to do this yourself.
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.
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've been trying to implement a C#-like event system in C++ with the tr1 function templates used to store a function that handles the event.
I created a vector so that multiple listeners can be attached to this event, i.e.:
vector< function<void (int)> > listenerList;
I'd like to be able to remove a handler from the list to stop a listener receiving events.
So, how can I find the entry in this list that corresponds to a given listener? Can I test if a 'function' object in the list refers to a particular function?
Thanks!
EDIT: Having looked into the boost::signal approach, it seems it's probably implemented using a token system as some of you have suggested. Here's some info on this. An observer retains a "Connection" object when they attach to an event, and this connection object is used to disconnect if needed. So it looks like whether you use Boost or roll your own with tr1, the basic principle's the same. i.e. it will be a bit clumsy :)
I don't know if you're locked into std C++ and tr1, but if you aren't, it seems like your problem could be completely avoided if you just used something like boost::signal and boost::bind to solve your original problem - creating an event system - instead of trying to roll your own.
Okay, you got me working. The hard part is trying to match the exact usage pattern of C# events. If you skip that, there are MUCH easier ways to do what you're asking. (My co-worker Jason uses a Notifier object all over the place.) Anyway, here's the incredibly boring code which does what you want. Unfortunately, it doesn't allow you to pass parameters from the Subject to the Observer. To do that, you'd need to add even more smarts.
#include "stdafx.h"
#include <iostream>
#include <string>
#include <list>
#include <algorithm>
#include <boost/tr1/functional.hpp>
#include <boost/tr1/memory.hpp>
using namespace std;
using namespace std::tr1;
template <typename T>
class ObserverHandle
{
public:
typedef boost::function<void (T*)> const UnderlyingFunction;
ObserverHandle(UnderlyingFunction underlying)
: _underlying(new UnderlyingFunction(underlying))
{
}
void operator()(T* data) const
{
(*_underlying)(data);
}
bool operator==(ObserverHandle<T> const& other) const
{
return (other._underlying == _underlying);
}
private:
shared_ptr<UnderlyingFunction> const _underlying;
};
class BaseDelegate
{
public:
virtual bool operator==(BaseDelegate const& other)
{
return false;
}
virtual void operator() () const = 0;
};
template <typename T>
class Delegate : public BaseDelegate
{
public:
Delegate(T* observer, ObserverHandle<T> handle)
: _observer(observer),
_handle(handle)
{
}
virtual bool operator==(BaseDelegate const& other)
{
BaseDelegate const * otherPtr = &other;
Delegate<T> const * otherDT = dynamic_cast<Delegate<T> const *>(otherPtr);
return ((otherDT) &&
(otherDT->_observer == _observer) &&
(otherDT->_handle == _handle));
}
virtual void operator() () const
{
_handle(_observer);
}
private:
T* _observer;
ObserverHandle<T> _handle;
};
class Event
{
public:
template <typename T>
void add(T* observer, ObserverHandle<T> handle)
{
_observers.push_back(shared_ptr<BaseDelegate>(new Delegate<T>(observer, handle)));
}
template <typename T>
void remove(T* observer, ObserverHandle<T> handle)
{
// I should be able to come up with a bind2nd(equals(dereference(_1))) kind of thing, but I can't figure it out now
Observers::iterator it = find_if(_observers.begin(), _observers.end(), Compare(Delegate<T>(observer, handle)));
if (it != _observers.end())
{
_observers.erase(it);
}
}
void operator()() const
{
for (Observers::const_iterator it = _observers.begin();
it != _observers.end();
++it)
{
(*(*it))();
}
}
private:
typedef list<shared_ptr<BaseDelegate>> Observers;
Observers _observers;
class Compare
{
public:
Compare(BaseDelegate const& other)
: _other(other)
{
}
bool operator() (shared_ptr<BaseDelegate> const& other) const
{
return (*other) == _other;
}
private:
BaseDelegate const& _other;
};
};
// Example usage:
class SubjectA
{
public:
Event event;
void do_event()
{
cout << "doing event" << endl;
event();
cout << "done" << endl;
}
};
class ObserverA
{
public:
void test(SubjectA& subject)
{
subject.do_event();
cout << endl;
subject.event.add(this, _observe);
subject.do_event();
subject.event.remove(this, _observe);
cout << endl;
subject.do_event();
cout << endl;
subject.event.add(this, _observe);
subject.event.add(this, _observe);
subject.do_event();
subject.event.remove(this, _observe);
subject.do_event();
subject.event.remove(this, _observe);
cout << endl;
}
void observe()
{
cout << "..observed!" << endl;
}
private:
static ObserverHandle<ObserverA> _observe;
};
// Here's the trick: make a static object for each method you might want to turn into a Delegate
ObserverHandle<ObserverA> ObserverA::_observe(boost::bind(&ObserverA::observe, _1));
int _tmain(int argc, _TCHAR* argv[])
{
SubjectA sa;
ObserverA oa;
oa.test(sa);
return 0;
}
And here's the output:
doing event
done
doing event
..observed!
done
doing event
done
doing event
..observed!
..observed!
done
doing event
..observed!
done
FAQ #1 in the boost function documentation seems to address your question - and the easy answer is "no".
The proposal (section IIIb.) states they will not be comparable in any way. If you attach some extra information to them, you can easily identify each callback. For instance, if you simply define a struct wrapping the function pointer, you can remove them (assuming you have the same struct you inserted). You can also add some fields to the struct (like an automatically generated guid the client can hold on to) and compare against that.
If you are storing function pointers only (and not other functors that match the signature required), this is easy (see code below). But in general, the answer, like other posters have said, is no. In that case, you probably want to store your functors in a hash, as values, with keys being something the user supplies on adding and removing.
The code below demonstrates how to get the functor/pointer object that is to be called. To use it, you must know the exact type of the object to extract (i.e., the typeid of the type you specify must match the typeid of the contained functor/pointer).
#include <cstdio>
#include <functional>
using std::printf;
using std::tr1::function;
int main(int, char**);
static function<int (int, char**)> main_func(&main);
int
main(int argc, char** argv)
{
printf("%p == %p\n", *main_func.target<int (*)(int, char**)>(), &main);
return 0;
}
What about
map<key-type, function<void (int)> > listeners;
I had a similar problem and found a solution to it. I used some C++0x features, but only for convenience, they are not an essential part. Take a look here:
> Messaging system: Callbacks can be anything