I myself am not exactly sure what I am asking for here, so please bear with me for a second.
Basically, I have an application that has to, amongst other things, be able to process commands that are received from some external source, let's say a socket.
Every command uses two data structures specific to this command - one structure holds a set of arguments relevant to the processing of this command, the other one receives some resulting data.
Naturally, data transfer handler class knows nothing about which command uses which structures, so the first thing that is invoked after command is received looks like this:
CSocketHandler::ReceiveCommand(int CommandCode, const TBuffer& Args, TBuffer& Result);
And the last one looks like this:
CClassBar::ProcessCommandFoo(const TFooArgs& Args, TFooResult& Result);
Now, all that's missing is the part that converts TBuffer to TFooArgs, invokes a correct method, then converts TFooResult back to TBuffer (A conversion is trivial).
The amount of different handler classes and commands promises to be quite large, so what I am looking at here is a method three miles long that does the same thing to different data types then calls different functions over and over again.
So my question - is it possible to automate this tedious and error prone task? Preferably to the point where just defining a new message handling method would be enough, but I am willing to compromise.
Generic code is good.
Create two convert methods, one from TBuffer to XArgs and the other from XResult to TBuffer
Create an automatic command wrapper
Implement a map to automatically dispatch to those wrappers
You can do it either through pointer to functions or inheritance, I suppose inheritance will be easier...
class BaseCommand {
public:
virtual ~BaseCommand() {}
virtual TBuffer invoke(TBuffer const& tb) = 0;
};
template <typename Args, typename Result>
class CommandT: public BaseCommand {
public:
virtual TBuffer invoke(TBuffer const& tb) {
Args const a = from_buffer(tb, &a); // free function
Result const r = this->invoke(a);
return to_buffer(r); // free function
}
private:
virtual Result invoke(Args const&) = 0;
};
Note: as a cheat, we pass &a to from_buffer to get automatic argument deduction, it is expected that the pointer is unused.
So, let us suppose that we have our arguments and results (both int it's easier):
int from_buffer(TBuffer const& tb, int const*) {
return tb.asInt();
}
TBuffer to_buffer(int i) {
return TBuffer(i);
}
And then we can implement a command that deals with int:
class IntCommand: public CommandT<int, int> {
virtual int invoke(int const& i) override { return i; }
};
Okay, let us move on to the dispatch. The idea is to register each command to its ID.
template <typename T>
std::unique_ptr<BaseCommand> make_command() { return std::unique_ptr<T>(new T()); }
static std::map<int, std::unique_ptr<BaseCommand>> Commands;
int main() {
Commands.insert(std::make_pair(1, make_command<IntCommand>()));
// lots of them...
// starts processing
}
And in SocketHandler we have:
void SocketHandler::ReceiveCommand(int code, TBuffer const& a, TBuffer& r) {
typedef std::map<int, std::unique_ptr<BaseCommand>>::const_iterator const_it;
const_it it = Commands.find(code);
if (it == Commands.end()) {
std::cerr << "Unknown command: " << code << "\n";
throw std::runtime_error("Unknown command");
}
r = it->second->invoke(a);
}
Related
I'm working on a code where I can bind events and callbacks to react to those events, the interface looks like this:
void on_close();
struct S
{
void the_app_is_closing();
};
S s;
Events::Register(app::CLOSE, on_close);
Events::Register(app::CLOSE, s, &S::the_app_is_closing);
...
...
if (/* something happens */)
Events::Broadcast(app::CLOSE);
Internally it keeps a container which associates an enum value identifying an event with all the functions expected to react to that event. Those functions are kept into an object which can hold free functions or member functions and feeds the functions through a template function (apply) that forwards the parameters:
class callback
{
struct base {};
template <typename ... params_pack>
struct callable : public base
{
callable(void(*a_function)(params_pack ...)) :
m_call{a_function}
{}
template <typename listener_t>
callable(listener_t &a_listener, void(listener_t:: *a_function)(params_pack ...)) :
m_call{[&a_listener, &a_function](params_pack ... a_argument)
{
(a_listener.*a_function)(a_argument ...);
}}
{}
std::function<void(params_pack ...)> m_call;
};
template <typename ... params_pack>
auto build(void(*a_function)(params_pack ...))
{
return std::make_unique<callable<params_pack ...>>(a_function);
}
template <typename listener_t, typename ... params_pack>
auto build(listener_t &a_listener, void(listener_t:: *a_function)(params_pack ...))
{
return std::make_unique<callable<params_pack ...>>(a_listener, a_function);
}
std::unique_ptr<base> m_function{nullptr};
public:
template <typename function_t>
callback(function_t a_function) :
m_function{build(a_function)}
{}
template <typename listener_t, typename function_t>
callback(listener_t &a_listener, function_t a_function) :
m_function{build(a_listener, a_function)}
{}
template <typename ... params_pack>
void apply(params_pack ... a_argument) const
{
if (auto &call = *static_cast<callable<params_pack ...> *>(m_function.get());
std::is_invocable_v<decltype(call.m_call), params_pack ...>)
{
call.m_call(a_argument ...);
}
}
};
I have an important bug on that apply function that can be reproduced with this code:
void string_parameter(const std::string &s) { std::cout << s << '\n'; }
void long_parameter(long l) { std::cout << l << '\n'; }
int main()
{
callback l(long_parameter);
callback s(string_parameter);
l.apply(123);
s.apply("Test");
return 0;
}
Even if you can call string_parameter directly with a literal string and long_parameter directly with a literal integer, doing the call through callback::apply messes everything up. I know why it is happening:
I'm static_casting callback::callable<const std::string &> to callback::callable<const char *>.
Then the callable::m_call which underlying type is std::function<const std::string &> thinks it is std::function<const char *>.
The callable::m_call receives a literal string but is reinterpreted as std::string during the std::function call, creating the mess.
Same story with long and int.
The solution would be to save the parameter pack used on construction in order to use it inside apply:
template <typename function_t>
callback(function_t a_function) :
m_function{build(a_function)}
{ PARAMETERS = function_t.parameters } // ???
template <typename listener_t, typename function_t>
callback(listener_t &a_listener, function_t a_function) :
m_function{build(a_listener, a_function)}
{ PARAMETERS = function_t.parameters } // ???
...
...
template <typename ... params_pack>
void apply(params_pack ... a_argument) const
{
// Saved parameters --> vvvvvvvvvvvvvv
if (auto &call = *static_cast<callable<PARAMETERS ...> *>(m_function.get());
std::is_invocable_v<decltype(call.m_call), params_pack ...>)
{
call.m_call(a_argument ...);
}
}
But I don't know if this is even possible. Any advise?
Thanks!
tl;dr:
Completely abstracting away the signature of the function AND still calling it in a type-safe way is impossible in C++
A type-based event system could be a good alternative
1. Why it's impossible to do what you're asking for
1.1 How Type-Erasure works
Type-erasure is fundamentally based on polymorphism. By defining a set of methods that all objects we want to store have in common (the interface) we don't need to know the actual type we're dealing with.
There is no way to do type-erasure without involving polymorphism.
For example, a very crude implementation of std::function could look like this:
template<class RetVal, class... Args>
class function {
public:
template<class U>
function(U u) : ptr(new impl<U>(u)) {}
~function() { delete ptr; }
RetVal operator()(Args... args) {
return ptr->call(args...);
}
private:
struct base {
virtual ~base() = default;
virtual RetVal call(Args... args) = 0;
};
template<class T>
struct impl : base {
impl(T t): t(t) {}
RetVal call(Args... args) override {
return t(args...);
}
private:
T t;
};
base* ptr;
};
template<class RetVal, class... Args>
class function<RetVal(Args...)> : public function<RetVal, Args...> {};
godbolt example
This is how std::function accomplishes to store any function object that is compatible with it's signature - it declares an interface (base) that will be used by all function objects (impl).
The interface only consists of 2 functions in this case:
The destructor (we need to know how to properly cleanup the function object)
The call() function (for invoking the actual function)
Sidenote 1: A real std::function implementation would need a couple more interface functions, e.g. for copying / moving the callable
Sidenote 2: Your existing implementation has a small bug: struct base MUST have a virtual destructor, otherwise the destructor of struct callable would never be called, resulting in undefined behaviour.
1.2 How your callable would need to work
What you want is an object that completely erases both the function object AND the parameters that you pass.
But what should your interface then look like?
struct base {
virtual ~base() = default;
virtual ??? call(???); // how should this work?
};
This is the underlying problem you're facing - it's impossible to define an interface for your callable - because you don't know what the arguments are gonna be.
This is what #Yakk - Adam Nevraumont implied with "non-uniform" objects - there is no definition of call() that can handle all potential function types.
1.3 Options
So at that point you basically have two options:
Don't erase the function type (like #Yakk - Adam Nevraumont suggested)
Sacrifice compile-time type safety and maintainability by creating an interface that can deal with arbitrary function types
The latter option is what your code currently uses - either the function parameters match or your code has undefined behaviour.
A few other ways to implement it that don't rely on undefined behaviour could be:
Add an interface function for each possible argument combination
struct base {
/* ... */
// All possible ways a `callable` could potentially be invoked
virtual void call(int val0) { throw std::exception("invalid call"); };
virtual void call(std::string val0) { throw std::exception("invalid call"); };
virtual void call(const char* val0) { throw std::exception("invalid call"); };
virtual void call(int val0, std::string val1) { throw std::exception("invalid call"); };
virtual void call(int val0, const char* val1) { throw std::exception("invalid call"); };
// etc...
}
// then implement the ones that are sensible
struct callable<std::string> : public base {
/* ... */
void call(std::string val0) override { /* ... */ }
void call(const char* val0) override { /* ... */ }
}
This obviously gets out of hand rather quickly.
"Accept anything" interface
struct base {
/* ... */
virtual void call(std::any* arr, int length);
};
// then implement the ones that are sensible
struct callable<std::string> : public base {
/* ... */
void call(std::any* arr, int length) override {
if(length != 1) throw new std::exception("invalid arg count");
// will throw if first argument is not a std::string
std::string& value = std::any_cast<std::string&>(arr[0]);
/* ... */
}
};
A bit better, but still looses compile-time type safety.
1.4 Conclusion
Compile-time type-safety with type-erasure is only possible if there is an uniform interface for all possible objects.
It is technically possible to type-erase non-uniform objects, but if you do that you'll loose compile-time type-safety (and need to do those checks at runtime instead)
2. Another Approach: Type-Based Event System
I'd like to propose a different way to handle the events that allows you to have arbitrary events without having to hard-code them into your Events class.
2.1 Basic Functionality
The main idea of this implementation is to have a class for each event you'd want to have that contains the parameters for the given event, e.g.:
struct AppClosingEvent {
const std::string message;
const int exitCode;
};
struct BananaPeeledEvent {
const std::shared_ptr<Banana> banana;
const std::shared_ptr<Person> peeler;
};
// etc...
This would then allow you to use the type of the event struct as a key for your event listeners.
A very simple implementation of this event system could look like this: (ignoring unregistration for now)
class EventBus {
private:
using EventMap = std::multimap<std::type_index, std::function<void(void*)>>;
// Adds an event listener for a specific event
template<class EvtCls, class Callable>
requires std::is_invocable_v<Callable, EvtCls&>
inline void Register(Callable&& callable) {
callbacks.emplace(
typeid(EvtCls),
[cb = std::forward<Callable>(callable)](void* evt) {
cb(*static_cast<EvtCls*>(evt));
}
);
}
// Broadcasts the given event to all registered event listeners
template<class EvtCls>
inline void Broadcast(EvtCls& evt) {
auto [first, last] = callbacks.equal_range(typeid(EvtCls));
for(auto it = first; it != last; ++it)
(it->second)(&evt);
}
private:
EventMap callbacks;
};
Register() takes a callable object that needs to be invocable with the given event type. Then it type-erases the callable so we can store it as a std::function<void(void*>
Broadcast(evt) looks up all event listeners that are registered based on the type of the event object and calls them.
Example Usage would look like this:
EventBus bus;
bus.Register<AppClosingEvent>([](AppClosingEvent& evt) {
std::cout << "App is closing! Message: " << evt.message << std::endl;
});
bus.Register<BananaPeeledEvent>([](BananaPeeledEvent& evt) {
// TODO: Handle banana peeling
});
AppClosingEvent evt{"Shutting down", 0};
bus.Broadcast(evt);
By using the type of the event as the key both Register() and Broadcast() are completely type-safe - it's impossible to register a function with incompatible function arguments.
Additionally the EventBus class doesn't need to know anything about the events it'll handle - adding a new event is as simple as defining a new class with the members you need for your event.
2.2 Adding the ability to unregister an event listener
I chose to use a multimap in this case because they guarantee to not invalidate iterators, unless the element the iterator points to itself gets removed from the multimap - which allows us to use a multimap iterator as the registration token for the event handler.
Full implementation: godbolt example
/*
EventBus - allows you to register listeners for arbitrary events via `.Register()`
and then later invoke all registered listeners for an event type with `.Broadcast()`.
Events are passed as lvalues, to allow event handlers to interact with the event, if required.
*/
class EventBus {
private:
using EventMap = std::multimap<std::type_index, std::function<void(void*)>>;
public:
/*
Represents a registered event handler on the EventBus.
Works a lot like std::unique_ptr (it is movable but not copyable)
Will automatically unregister the associated event handler on destruction.
You can call `.disconnect()` to unregister the event handler manually.
*/
class Connection {
private:
friend class EventBus;
// Internal constructor used by EventBus::Register
inline Connection(EventBus& bus, EventMap::iterator it) : bus(&bus), it(it) { }
public:
inline Connection() : bus(nullptr), it() {}
// not copyable
inline Connection(Connection const&) = delete;
inline Connection& operator=(Connection const&) = delete;
// but movable
inline Connection(Connection&& other)
: bus(other.bus), it(other.it) {
other.detach();
}
inline Connection& operator=(Connection&& other) {
if(this != &other) {
disconnect();
bus = other.bus;
it = other.it;
other.detach();
}
return *this;
}
inline ~Connection() {
disconnect();
}
// Allows to manually unregister the associated event handler
inline void disconnect() {
if(bus) {
bus->callbacks.erase(it);
detach();
}
}
// Releases the associated event handler without unregistering
// Warning: After calling this method it becomes impossible to unregister
// the associated event handler.
inline void detach() {
bus = nullptr;
it = {};
}
private:
EventBus* bus;
EventMap::iterator it;
};
// Adds an event listener for a specific event
template<class EvtCls, class Callable>
requires std::is_invocable_v<Callable, EvtCls&>
inline Connection Register(Callable&& callable) {
auto it = callbacks.emplace(
typeid(EvtCls),
[cb = std::forward<Callable>(callable)](void* evt) {
cb(*static_cast<EvtCls*>(evt));
}
);
return { *this, it };
}
// Broadcasts the given event to all registered event listeners
template<class EvtCls>
inline void Broadcast(EvtCls& evt) {
auto [first, last] = callbacks.equal_range(typeid(EvtCls));
for(auto it = first; it != last;)
(it++)->second(&evt);
}
private:
EventMap callbacks;
};
With this you can easily register listeners and unregister them later (e.g. if the class they're bound to gets destructed)
Example:
struct DispenseNachosEvent {};
struct DispenseCheeseEvent {};
class NachoMachine {
public:
NachoMachine(EventBus& bus) {
// register using std::bind
nachoEvent = bus.Register<DispenseNachosEvent>(
std::bind(
&NachoMachine::OnDispenseNachos,
this,
std::placeholders::_1
)
);
// register with lambda
cheeseEvent = bus.Register<DispenseCheeseEvent>(
[&](DispenseCheeseEvent& evt) {
OnDispenseCheese(evt);
}
);
}
// Default destructor will automatically
// disconnect both event listeners
private:
void OnDispenseNachos(DispenseNachosEvent&) {
std::cout << "Dispensing Nachos..." << std::endl;
}
void OnDispenseCheese(DispenseCheeseEvent&) {
std::cout << "Dispensing Cheese..." << std::endl;
}
private:
EventBus::Connection nachoEvent;
EventBus::Connection cheeseEvent;
};
2.3 Other benefits
If you want you can also allow the event handlers to modify the event object - e.g. cancel it - which allows you to return state to the piece of code that called Broadcast()
Example:
struct CancelableExampleEvent {
inline void Cancel() { isCancelled = true; }
inline bool IsCancelled() { return isCancelled; }
CancelableExampleEvent(std::string message) : message(message) {}
const std::string message;
private:
bool isCancelled = false;
};
// Usage:
CancelableExampleEvent evt;
bus.Broadcast(evt);
if(!evt.IsCancelled()) {
// TODO: Do something
}
Event Handlers can remove themselves - this is usually tricky to implement due to iterators being invalidated, but with multimaps it's rather easy to implement:
template<class EvtCls>
inline void Broadcast(EvtCls& evt) {
auto [first, last] = callbacks.equal_range(typeid(EvtCls));
for(auto it = first; it != last;)
(it++)->second(&evt);
}
By incrementing it before calling the function we make sure that it remains valid, even if the event handler chooses to unregister itself as part of its callback.
e.g. this would work:
EventBus::Connection con;
con = bus.Register<SomeEvent>([&con](SomeEvent&){
std::cout << "Received event once!" << std::endl;
con.disconnect();
});
2.4 Try it online!
Here's a godbolt that contains the entire code of this post to try it out.
This is your problem:
class callback
it should be
template<class...Args>
class callback
because you have to think about what happens when the types do not match
void string_parameter(const std::string &s) { std::cout << s << '\n'; }
void long_parameter(long l) { std::cout << l << '\n'; }
callback<long> l(long_parameter);
callback<std::string> s(string_parameter);
l.apply(123);
s.apply("Test");
which works flawlessly.
Now you run into the problem of a central enum for all callbacks.
Events::Register(app::CLOSE, on_close);
Events::Register(app::CLOSE, s, &S::the_app_is_closing);
The problem is that all use of app::CLOSE must know what the signature of the callback must be. The code registering it must know, and the code invoking the callback must know.
Your design, however, carefully forgets this fact, and forces type unsafety at both ends. Then you add so,e template code in the middle to ferry types around... which even if it did work, would be work for no good reason.
template<app::event e>
void Events::Register(event_sig<e>* pf);
template<app::event e, class T>
void Events::Register(T* pt, event_mem_sig<T,e>* pf);
template<app::event e, class...Ts>
void Event::Broadcast(Ts&&....ts);
here we have a more sensible API. The event type is compile time value, so we can do type checking, and store the event callbacks in a type safe list.
...
Now, if you have a reasonably bounded number of events (ie, not 1000s of which under 1% are subscribed to), an even simpler solution is to make an event queue an actual object, instead of an enum and traits.
using token=std::shared_ptr<void>;
template<class...Args>
struct broadcaster {
size_t broadcast(Ts...ts)const;
token subscribe(std::function<void(Ts...)>);
void unsafe_subscribe(void(*)(Ts...));
// IMPLEMENTATION
};
now your code becomes
struct Events {
broadcaster<> appClosing;
};
Events g_events;
struct S
{
void the_app_is_closing();
token listening;
};
S s;
s.listening=g_events.appClosing.subscribe(&s, &S::the_app_is_closing);
g_events.appClosing.unsafe_subscribe(on_close);
g_events.appClosing.broadcast();
The types of the arguments are now tied to the appClosing object, so it is checked at both sibscription and at broadcast, conversion is done automatically.
Here each broadcaster maintains its own listener queue (hence bit above about "1000s of event types most unused). Extra work can be done to reduce the queue storage and share it, but that should onlh be done if you need it. And you probably won't.
The enum solution seems like it reduces duplication, but uniform lists of things with non uniform types are often a sign your list shoudln't be uniform.
Members of a struct are a fine way to list non uniform things. Having them be generated from a template means there isn't code writing duplication. And identical signature broadcasters will share binary implementations, somit isn't inefficient.
I have a program in which I would like to choose a set of types (from predefined lists) at run time, not compile time.
Below is an example of the kind of code I'd like to run; Even and Log are types to define a numerical grid, and deriv_Ox is a differentiation scheme of order x:
struct Even {
double a, b;
};
struct Log {
double a, x0, b;
};
// ...
struct deriv_O2 {
vec_type operator() (const vec_type & f_points) const;
};
struct deriv_O4 {
vec_type operator() (const vec_type & f_points) const;
};
// ...
template <class grid_type, class deriv_type>
void run_calculation (const std::string param_file) {
auto grid = grid_from_file<grid_type>(param_file);
auto deriv = deriv_from_file<deriv_type>(param_file);
// ...
}
I would like to decide which of these types to use at run time, by reading a parameter file. My solution was to use tags and case statements to decide which type to use from a single list, then nest each case statement in a function deciding each type in the set as follows:
enum struct grid_tag { Even, Log };
enum struct deriv_tag { O4, O2 };
grid_tag grid_tag_from_file (const char file_name[]);
deriv_tag deriv_tag_from_file (const char file_name[]);
template <class deriv_type>
void run_calculation (const grid_tag g,
const std::string param_file) {
switch(g) {
case grid_tag::Even:
run_calculation<Even, deriv_type>(param_file);
break;
case grid_tag::Log:
run_calculation<Log, deriv_type>(param_file);
break;
}
}
void run_calculation (const grid_tag g, const deriv_tag d,
const std::string param_file) {
switch(d) {
case deriv_tag::O4:
run_calculation<deriv_O4>(g, param_file);
break;
case deriv_tag::O2:
run_calculation<deriv_O2>(g, param_file);
break;
}
}
int main (int argc, char * argv[]) {
grid_tag g = grid_tag_from_file(argv[1]);
deriv_tag d = deriv_tag_from_file(argv[1]);
run_calculation(g, d, argv[1]);
}
The problem is that I have a set of ~6 types to choose from lists of size ~10, and these will grow in the future. The solution I have at the moment makes adding new types awkward.
Is this solution the best I'm going to do? Am I being very fussy, or is there a better solution someone can suggest? I have looked at boost::variant (as recommended in similar questions) but I don't think this is really suitable for what I want to do.
As written, this leads to "double dispatch", which is not an easy thing to solve in C++ (see e.g. here: Understanding double dispatch C++).
What might be applicable in this case, instead of having:
template <class grid_type, class deriv_type>
void run_calculation (const std::string param_file) {
auto grid = grid_from_file<grid_type>(param_file);
auto deriv = deriv_from_file<deriv_type>(param_file);
// ...
}
to retrieve the grid/deriv from the file and result in a concrete type, to have instead
void run_calculation (const std::string param_file, grid_tag gtag, deriv_tag dtag) {
auto /*Grid interface*/ grid = grid_from_file(param_file, gtag);
auto /*Deriv interface*/ deriv = deriv_from_file(param_file, dtag);
// ...
}
and using virtual function call on the Grid/Deriv interface to do the stuff.
(if you do not want to pollute the original grid/deriv classes by the virtual methods, you could also create wrappers for them)
The advantage of this (of course if applicable to your actual situation) would be, that you would not need to solve all the combinations. Compared to the "switch" solution (works in a similar way), you do not need to remember to put switches everywhere to decide the types, you can just call the appropriate virtual functions to do the work (and if the virt. functions are pure in the interface, you cannot forget to provide them, because it will not compile otherwise).
Also, instead of grid_tag, deriv_tag, you could provide a virtual method on the interfaces to read from the file appropriately.
And I would also recommend to pass the string by const ref ("const std::string & param_file"), not by value (copies made).
Selecting a type from a runtime value inherently have some ugliness involved, but judging from the snippet provided, a table of functions would work just fine
enum struct grid_tag { Even, Log, size };
enum struct deriv_tag { O4, O2, size };
using calculation = void (*)(std::string);
calculation table[grid_tag::size][deriv_tag::size]; // populate them
void run_calculation (const grid_tag g, const deriv_tag d, const std::string& param_file)
{
table[g][d](param_file);
}
You can solve this creating several interface (abstract virtual classes with no method implemented) , one for each type you want to decide at runtime.
You then can use a template method pattern to write your algorithm using the interfaces you have written.
This way, adding elements to the lists of type is just adding a new class implementing the interface.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
pure virtual function and abstract class
I have a class and I want to create a virtual function that will be used to print debug information. Any class that inherits this class will have to implement this virtual function. This way different classes could print the debug messages to different output devices such as std::cout, labels, files etc.
The base class won't be aware of the messages destination. But I don't know the best way to do this. I'm thinking of using something like printf() which can print an arbitrary number of parameters. But I don't know what that would be accomplished. Any ideas?
There is a disadvantage to the approach that you propose. Every derived class will have to implement a printf like facility themselves. That doesn't seem like a very productive activity, and it would make the base class very annoying to use.
It may be less burdensome, code wise, to have the base class require the derived classes provide a debug ostream. Or, you could default to cerr.
class Base {
protected:
virtual std::ostream & debug_stream () const { return std::cerr; }
//...
};
Then, an external user of Base can poke info into the debug_stream.
If you insist on printf style syntax, the interface could return a FILE * instead:
class Base {
protected:
virtual FILE * debug_file () const { return stderr; }
//...
};
So, for example, a derived class could do this:
class Derived : public Base {
static std::ofstream dbgstream;
std::ostream & debug_stream () const { return dbgstream; }
//...
};
std::ofstream Derived::dbgstream("/tmp/derived.dbg");
Then if one has proper access to the base class interface,
void foo (Base *b) {
//...do something with b
b->debug_stream()
<< __FILE__ << ":" << __LINE__ << " foo did something"
<< std::endl;
//...
}
I would do something like this:
class Base
{
protected:
virtual int doDebug(const std::string& Msg) const = 0;
public:
int Debug(const char* MsgFmt, ...) const;
};
int Base::Debug(const char* MsgFmt, ...) const
{
std::string sMsg;
va_list args;
va_start(args, MsgFmt);
int len = vsnprintf(NULL, 0, MsgFmt, args);
if (len > 0)
{
sMsg.resize(len);
vsnprintf(&sMsg[0], len + 1, MsgFmt, args);
}
va_end(args);
return doDebug(sMsg);
}
That way, you still provide the caller with flexible formatting, but the derived classes do not have to worry about that because they are given only pre-formatted text.
I would just do this
class Base
{
virtual int debugfn(const std::string& msg) const = 0;
};
I.e., don't mix the functionality of printf (producing a formatted string and sending it to stdout) with the debugging function. Let it take as its argument a string that is already complete, and let the derived classes decide what to do with it. The int can be an error code if desired, otherwise just return void.
The basic idea here is to use a protected virtual function that takes a string as the error/log/debug-message to be printed / logged. Then, your base class exposes a non-virtual function (or set of functions) to construct the string that will be fed to the protected virtual function. To actually create the string, you can use one of many ways, in the style of printf (with varargs or variadic templates (C++11)), or in the style of standard iostreams. Here is one solution in the latter category:
class BaseDebugOutput {
protected:
virtual void printMessage(const std::string& aMsg) = 0;
private:
std::stringstream temp_stream;
public:
virtual ~BaseDebugOutput() { };
// One << operator for any type.
template <typename T>
BaseDebugOutput& operator<<(const T& value) {
temp_stream << value;
return *this;
};
typedef std::basic_ostream< std::stringstream::char_type,
std::stringstream::traits_type >&
(*ostream_function_ptr)(
std::basic_ostream< std::stringstream::char_type,
std::stringstream::traits_type >&);
// One << operator for things like std::endl.
BaseDebugOutput& operator<<(ostream_function_ptr p) {
if(p == ostream_function_ptr(std::endl)) {
// if the user outputted an end-line, then print the entry:
temp_stream << std::endl;
std::string temp_msg;
std::getline(temp_stream,temp_msg);
// call the protected virtual function:
printMessage(temp_msg);
} else {
temp_stream << p;
};
return *this;
};
};
An example derived class would be:
class CErrDebugOutput : public BaseDebugOutput {
protected:
virtual void printMessage(const std::string& aMsg) {
std::cerr << "Error reported with message: '" << aMsg << "'." << std::endl;
};
};
And the use-case would look like this:
int main() {
BaseDebugOutput* debug_output = new CErrDebugOutput;
(*debug_output) << "The answer is: " << 42 << "!" << std::endl;
delete debug_output;
return;
};
One advantage of the above setup is that you can insert almost anything you want in addition to the error message, such as a time-stamp for example, or just adding the "Error: " string or whatever so that you don't have to repeat that all the time at the points where you issue the messages (call-site).
I might not have understood the question, because the simplest thing that comes to mind has not been offered in all the other answers... If the intention is providing a single entry point for all the hierarchy to print information, then this is the simplest approach:
class base {
public:
virtual std::ostream& print( std::ostream& /*...*/ ) const = 0;
};
std::ostream& operator<<( std::ostream& o, base const & b ) {
return b.print( o );
}
The comment /*...*/ is there because, unlike operator<< the signature is not fixed, so you could pass extra arguments to control the formatting (say, bool single_line, int indent --if !single_line to insert leading spaces, int verbosity to control whether only the public state of the object is to be printed or also auxiliary data...) to produce richer output.
With a single implementation (and a forwarding function) you get printing of the objects to a stream and a way of generating logs with the state of your program for debugging.
If on the other hand what you mean is a solution for derived classes to print debug messages regarding their state at different points in time, then you cannot really do that polymorphically, as the decision to log messages and when should be taken by the derived types. In that case, just pull a logging library and use it. Common logging libraries have very little cost at runtime if the log level is lower than the type of messages (i.e. if you configure to log only warning, the cost of the debug logs (that will not be generated) is very small.
I have an application which will be receiving messages from another application. These messages will be XML fomatted strings, and they will contain a <messageType> tag. The message type will identify this message as a type of internal message. The following code shows my internal message structures.
namespace
Application1{
enum ApplicationAttributes{
ApplicationName = 1000,
Start,
Stop,
Pause,
Save,
Discard,
SelectRunway,
DoAlignment,
RedoAlignment,
AlignmentOK,
DoCalibrationStage1,
SetCalibrationStage1,
SetCalibrationStage2,
SetCalibrationStage3,
CancelCalibration,
CalibrationOK
};
struct Alignment{
int x;
int y;
int error;
};
struct Calibration{
int x;
int y;
int error;
};
}
alignment and calibration are the two internal message structures.
What I'm trying to do is build a 'message interpreter' which will receive an XML string, decode it and return any one of the structs shown above; so if the <messageType> is 'alignment', the message interpreter will build an alignment struct, and return that.
So ultimately, I'm trying to make a template function, which can return an arbitrary struct, based on what i read in from <messageType>.
Are my objectives clear? is my approach the right one?
Let me know if I should clarify, or if I should take a different approach.
I don't believe a template function makes sense. Your input is always going to be a string, and C++ can't differentiate function signatures based on return type alone - so I don't know how a template would help - what would the type argument be?
I'd suggest making your function a normal one that parses out the messageType and allocates a struct based on it - you can use whatever constructs you want for this.
The trick would be (in my mind) to derive all of your internal-message-classes from the same empty base class - you could then return a pointer to that base class back from your function, and it will hold whatever type got created.
It be a good idea to return an enumeration along with the pointer in a std::pair which you can use to determine the correct derived type that was created, that way you can cast the result directly to the correct derived type with a static_cast.
As I understand it your structures are known within the application, so what about this save variant:
class Message {
public:
static Message Alignment (alignment_t const &);
...
Type type() const;
int alignment() const;
private:
Message (Type t);
assert_type (Type t, const char *msg) const;
private:
Type type_;
};
Message Message::Alignment (alignment_t const &alignment)
{
Message ret (Type::Alignment);
ret.alignment_ = alignment;
return ret;
}
void Message::assert_type (Type t, const char *msg) const
{
if (type() != t) throw std::runtime_error (msg);
}
int Message::alignment() const
{
assert_type (Type::Alignment,
"alignment_x() called for non-alignment-message");
return alignment_;
}
(coded without verification to give you the idea)
This works without polymorphism (I use this pattern in a compiler for a LISP like language, where polymorphic trees would result in more complicated code). You can change it to return "alignment_x()" and so on, if you like that more.
Fully dynamic structures are not possible, and solutions that try to come near will be rather complicated. Use the most-maintainable solution.
If you write a factory function/functor for each type, you can associate that with the messageType (map<string, Factory*> will be sufficient), but what to return?
You can return some kind of discriminated union, or boost::variant, if you don't mind the top-level decoder depending on all possible message types.
But, what is the decoder going to do with this return value? If it just switches on the type and calls a type-specific callback in each case, you could invert control by attaching a callback function/functor to the factory directly.
Then the decoder doesn't return anything, it just constructs the message struct and passes it directly to a handler.
Simple implementation (OK, that was more typing than I thought):
class Decoder
{
public:
virtual ~Decoder();
virtual void decode(std::string const &xml) = 0;
};
template <typename Factory, typename Callback>
class SimpleDecoder: public Decoder
{
Factory factory;
Callback callback;
public:
SimpleDecoder(Factory f, Callback c)
: factory(f), callback(c)
{}
void decode(std::string const &xml)
{
callback( factory( xml ) );
}
};
std::map<std::string, Decoder*> factories;
template <typename F, typename C>
void registerSimpleDecoder(std::string const &n, F f, C c)
{
factories[n] = new SimpleDecoder(f, c);
}
void decodeXmlMessage(std::string const &messageType, std::string const &body)
{
factories[messageType]->decode(body);
}
using QMetaObject::newInstance, so you can create a QObject* that can be converted afterwards to your class using dynamic_cast
class MyClass : public QObject{
public:
enum Type{ MyClassType = UserType + 1 }
Q_INVOKABLE MyClass();
}
Q_DECLARE_METATYPE ( MyClass )
then, in your XML Parsing Code:
MyClass* myObject = (MyClass*) QMetaType::construct ( MyClass::MyClassType );
And things will work out.
My program reads in "commands" from a text file such as "w test.txt 5" for write to test.txt the number 5 or "r test.txt" for reading from test.txt. Instead of having a horrible switch loop to maintain I have a called aFunction which has function member
string name;
void (*thefunction)(char *argsIn[], char *out);
So I have a string name and a function pointer. Outside the class I have a
vector<aFunction> funcVec
which holds all the functions. When I read a command in from a text file the code looks through funcVec to find the correct function to call
So when funcVec.name = command read in
(*funcVec[i].theFunction(other values from the text file, output);
For example I may have the funciton read(char *argsIn[], char *out)
where argsIn would be an array containing test.txt, 5 and char out might be a 1 or 0 depending on whether the operation was successful.
However I don't really like this very much because all functions now have to have the signature (char *argsIn[], char *out) and it's up to the function to know what each parameter in the list means.
Can anyone think of a better implementation? Surely software that supports scripting has to cope with this sort of thing?
Note: you'd better use std::string and std::vector
The Command pattern is normally the way to do this, this allows "packing" the input/output arguments in the object and presenting a "blank" execution method void operator()() ensuring a common interface.
EDIT: a demonstration of Command (generic).
Define some commands:
struct Command: boost::noncopyable
{
virtual void do() = 0;
virtual void undo() = 0;
virtual ~Command() {}
};
class SaveFile: public Command
{
public:
explicit SaveFile(FileHandle f, Changes c): _file(file), _changes(c) {}
virtual void do() { _file.apply(_changes); }
virtual void undo() { _file.revert(_changes); }
private:
FileHandle _file;
Changes _changes;
};
class OpenFile: public Command
{
public:
explicit OpenFile(std::string filename): _filename(filename) {}
FileHandle get() const { return _file; }
virtual void do() { _file.load(_filename); }
virtual void undo() { /*nothing to be done*/ }
private:
std::string _filename;
FileHandle _file;
};
Example use of two stacks of actions: those to be performed, and those that have been performed.
typedef std::stack<std::unique_ptr<Command>> CommandStack;
void transaction(CommandStack& todo)
{
CommandStack undo;
try
{
while(!todo.empty())
{
todo.top()->do();
undo.push(std::move(todo.top()));
todo.pop();
}
}
catch(std::exception const&)
{
while(!undo.empty())
{
undo.top()->do();
undo.pop();
}
}
} // transaction
What you have to do reading these commands is threefold:
Find out which function to call.
Convert the list of argument strings into the arguments of the right type.
Call the function passing those arguments to do the whatever needs to be done.
To abstract #2 is pretty hard, as C++ has very little support for dealing with different types that are known only at runtime, but it's not impossible.
I have once seen an article where someone used template-meta programming to find out about the parameters of registered function, and then generate the code that breaks down string list into the matching arguments. Functions were kept in a map of key strings to function pointers (using type erasure to store functions with different signatures).
Here's a sketch about how to use type erasure to store different function pointer sin a map:
struct func_base {
virtual void operator()(std::istream&) const = 0;
};
template< typename F >
class function : public func_base {
public:
function(F f) : func_(f) {}
void operator()(std::string& arguments) const;
private:
func_base func_;
};
typedef std::map< std::string, std::shared_ptr<func_base> > func_map;
template< typename F >
void addFunc(func_map& map, const std::string& keyword, F f)
{
assert(map.find(keyword) == map.end());
map[keyword] = std::shared_ptr<func_base>(new function<T>(f));
}
That would leave function<F>::operator()() to chop the arguments into individual strings, convert them into the appropriate types, and then call the function with them.
Chopping the string into a list of arguments shouldn't be a problem, so I'll skip over that. The hard part is calling a function with the right parameters given that list. Note that the function's type is known within function<F>::operator()() at compile-time, so you have the whole of template-meta programming techniques at your disposal.
ISTR that article did this by creating tuples according to the function's parameter list and had the means to call any function given such a tuple. Here's you could create such tuples with recursive calls:
template< typename Tuple >
Tuple convert_args(const std::string& line)
{
Tuple result;
// I don't know tuples well enough yet, so here's just an
// algorithm rather than code:
// 1. read first argument from line and put it into tuple's first element
// 2. call yourself for a tuple that consists of the remaining elements of Tuple
// 3. fill the remaining tuple elements from the result of #2
return result
}
Then use traits to call those functions:
template<typename F>
struct func_traits;
template<typename R, typename A1>// function taking one arg
struct func_traits<R(*)()> {
typedef std::tuple<A1> arg_list;
static R call(R(*f)(), const arg_list& args)
{
return f(std::get<0>(arg_list)); // how do you access an element in a tuple
}
};
template<typename R, typename A1, typename A2>// function taking two args
struct func_traits<R(*)()> {
typedef std::tuple<A1,A2> arg_list;
static R call(R(*f)(), const arg_list& args)
{
return f(std::get<0>(arg_list), std::get<1>(arg_list));
}
};
// repeat for as many args as you'll need
A very simple implementation would be using std::map instead of std:vector which you've used:
typedef void (*FunctionType)(char *argsIn[], char *out);
std::map<std::string, FunctionType> functionMap;
//populate the functionMap
//key = commandName, value = function to be called;
functionMap["write"] = WriteFunc;
functionMap["read"]= ReadFunc;
//later use this map as
functionMap[commandName](arguments, output);