recursive c++ template problem - c++

Say I have a template class that takes msgs from source, does something smart to them, and then sends them to a sink:
template <typename Source, typename Sink>
class MsgHandler
{
MsgHandler(Source* pSource)
: m_pSource(pSource)
{
m_pSource->setHandler(this);
}
};
//Now the definition of the Source:
template <typename Handler>
class Source
{
void setHandler(Handler* pHandler)
{
m_pHandler = pHandler;
}
};
All fine, but now I can't really make a Source or Handler. Eg:
MsgHandler<FileSource<MsgHandler<FileSource.... recursing parameters...
FileSource<MsgHandler<FileSource<MsgHandler.... same problem when trying to build a source
Is there a way to solve this problem without using a virtual base class for the Handler?
Virtual base class solution:
class MyHandler
{
virtual ~MyHandler() {};
virtual void handleSomething() = 0;
};
template <typename Source, typename Sink>
class MsgHandler : public MyHandler
{
MsgHandler(Source* pSource)
: m_pSource(pSource)
{
m_pSource->setHandler(this);
}
void handleSomething() {}
};
class Source
{
void setHandler(MyHandler* pHandler)
{
m_pHandler = pHandler;
}
};

You could use a templated parameter for the source parameter of your handler:
class MySink;
template <template<typename Handler> class Source, typename Sink>
class MsgHandler
{
Source<MsgHandler>* m_pSource;
MsgHandler(Source<MsgHandler>* pSource)
: m_pSource(pSource)
{
m_pSource->setHandler(this);
}
};
//Now the definition of the Source:
template <typename Handler>
class Source
{
void setHandler(Handler* pHandler)
{
m_pHandler = pHandler;
}
};
//Now you can define variables like this
MsgHandler<Source, MySink> myHandler;
Of course that requires the Source parameter of MsgHandler to be a template with exactly one parameter (the handler), but if you can live with that constraint this would solve your definition problem (otherwise you might (or might not depending on what exactly you would be trying) be able to use some extra template foo to circumvent this restriction (creating another template which takes the handler as parameter and has a typedef for the corresponding SourcesType comes to mind).
In this scenario it might also be a good idea to add an typedef Source<MsgHandler> SourceType to MsgHandler to make the Source-Instantiation visible to the caller (instead of requiring the programmer to guess that MsgHandler will instantiate Source.

I don't understand why your Source needs to be parameterized on its handler. If Source and Handler really do need to be tightly coupled in the way you describe, it does not seem like templates buy you very much beyond interface definition. Seems to me like you could just have a non-template Source class that encapsulates Handler<Source, Sink>.

It looks like the Handler shouldn't know anything about the Source. How about simple linear dependency:
template <typename Sink>
class Handler {
private:
Sink* sink; // get this pointer in the constructor?
public:
void handle( const Msg& m ) {
// processing
sink->accept( m );
}
};
template <typename Handler>
class Source {
private:
Handler* handler;
public:
void genMessage() {
Msg m;
// get message off the wire?
handler->handle( m );
}
};
Could also be twisted to have "handling" and "sinking" as policies.

Related

Using template type to generate unique member names for that template type

This use case comes from wanting to implement a compile-time event bus data structure that only listens/registers/unregisters specifically for the provided template arguments.
Starting with a naive implemention lets say we have the following classes AListener, AEvent, BListener, BEvent.
I want my EventBus class to look like this:
class EventBus {
std::vector<AListener*> aListeners;
std::vector<BListener*> bListeners;
public:
void registerListener(AListener& listener);
void unregisterListener(AListener& listener);
void sendEvent(AEvent event);
void registerListener(BListener& listener);
void unregisterListener(BListener& listener);
void sendEvent(BEvent event);
};
Is there a way I can template it and recursively construct the class? For example:
EventBus<AListener, AEvent, BListener, BEvent> eventBus;
AListener aListener;
eventBus.registerListener(aListener);
AEvent aEvent;
eventBus.sendEvent(aEvent);
BListener bListener;
eventBus.registerListener(bListener);
BEvent bEvent;
eventBus.sendEvent(bEvent);
Preferably it'd be nice to make a new vector for each listener type because it would be inefficient to put all the pointers in one list since a long list of irrelevant listeners would be a waste of performance. Since the event bus is going to have a lot of events going through it, performance is important. Iterating over only the ones we care about is desired.
Finally, assume that we will not specialize any listener so we don't have to worry about inheritance here, all classes in the template list are considered to be final.
My problem:
How do I get around naming? While I assume specializing templates in the recursive definition via method overloading is okay because the compiler will hopefully do the ideal thing... I'm not sure how to handle the different member names.
My plan was to take the list and pull off two members, sort of like this (NOTE this is pseudo-code and almost certainly does not compile, or if it does it is by pure chance):
// Pseudocodey C++ template rough idea
template <typename Listener, typename Event, typename Args...>
class EventBus : public EventBus<Args...> {
// ???
public:
void registerListener(Listener& listener) {
// emplace back
}
void unregisterListener(Listener& listener) {
// erase remove
}
void sendEvent(Event event) {
// send for each
}
};
Of course unless there is a better way? Is this possible?
I would create a class to handle Listener/event:
template <typename Listener, Event>
class EventHandler {
std::vector<Listener*> mListeners;
public:
void registerListener(Listener& listener);
void unregisterListener(Listener& listener);
void sendEvent(Event event);
};
Then, your class which handles all would be:
template <typename ... Ts>
class EventBus : Ts...
{
public:
using Ts::registerListener...; // Requires C++17
using Ts::unregisterListener...; // Prior that you have to do it with recursion
using Ts::sendEvent...; // class EventBus<T, Rest...> : T, EventBus<Rest...>
};
With usage:
EventBus<EventHandler<AListener, AEvent>, EventHandler<BListener, BEvent>> eventBus;
Btw, Event is probably dependent of Listener, so having typename Listener::Event seems appropriate and remove all Event template parameters.
You can use a tuple and some type traits:
#include <iostream>
#include <vector>
#include <tuple>
#include <utility>
template<typename x_Event> class
t_EventTrait;
template<typename ... x_Listener> class
t_EventBus
{
private: ::std::tuple<::std::vector<x_Listener *>...> m_listeners;
public: template<typename xx_Listener> void
Register_Listener(xx_Listener & listener)
{
::std::get<::std::vector<xx_Listener *>>(m_listeners).emplace_back(&listener);
}
public: template<typename x_Event> void
Send_Event(x_Event & event)
{
for(auto p_listener: ::std::get<::std::vector<typename t_EventTrait<x_Event>::t_Listener *>>(m_listeners))
{
p_listener->On_Event(event);
}
}
};
struct t_EventA {};
struct t_ListenerA { void On_Event(t_EventA &) { ::std::cout << "handling A\n"; } };
template<> class t_EventTrait<t_EventA>{ public: using t_Listener = t_ListenerA; };
struct t_EventB {};
struct t_ListenerB { void On_Event(t_EventB &) { ::std::cout << "handling B\n"; } };
template<> class t_EventTrait<t_EventB>{ public: using t_Listener = t_ListenerB; };
int main()
{
t_EventBus<t_ListenerA, t_ListenerB> bus{};
t_ListenerA a{};
bus.Register_Listener(a);
t_EventA ea{};
bus.Send_Event(ea);
t_ListenerB b{};
bus.Register_Listener(b);
t_EventB eb{};
bus.Send_Event(eb);
return 0;
}
online compiler
In C++11, you can use a variadic template
template<class... MoreEventPairs> class EventBus {};
template<class Listener, class Event>
class EventBus<Listener, Event>
{
private:
std::vector<Listener *> Listeners;
public:
EventBus() {};
~EventBus() {};
void registerListener(Listener& listener) {}; // dummy implementations here
void unregisterListener(Listener& listener) {};
void sendEvent(Event event) {};
};
template<class Listener, class Event, class ... MoreEventPairs>
class EventBus<Listener, Event, MoreEventPairs ...> : public EventBus<Listener, Event>,
public EventBus<MoreEventPairs ...>
{
public:
// these are needed so name resolution works
// one needed for each function, on both inheritance paths
using EventBus<Listener, Event>::registerListener;
using EventBus<Listener, Event>::unregisterListener;
using EventBus<Listener, Event>::sendEvent;
using EventBus<MoreEventPairs ...>::registerListener;
using EventBus<MoreEventPairs ...>::unregisterListener;
using EventBus<MoreEventPairs ...>::sendEvent;
};
// construct as
EventBus<ListenerA, EventA, ListenerB, EventB> bus;
This works by essentially peeling two types at a time from the parameter pack. It will not compile if you supply an odd number of types when constructing (e.g. leave off an Event type). You can specialise handling for a particular type of Listener or associated Event by using specialisation of the two-parameter template.
Before C++11, you could use multiple inheritance, but would need to construct the EventBus class separately. This is more effort to maintain, due to need to replicate code to extend.
template<class Listener, class Event> class ListenerBus
{
private:
std::vector<Listener *> Listeners;
public:
ListenerBus() {};
~ListenerBus() {};
void registerListener(Listener& listener) {}; // dummy implementations here
void unregisterListener(Listener& listener) {};
void sendEvent(Event event) {};
};
// AListener, AEvent, etc are concrete classes
class EventBus : public ListenerBus<AListener, AEvent>,
public ListenerBus<BListener, BEvent>
// list other types here
{
public:
using ListenerBus<AListener, AEvent>::registerListener;
using ListenerBus<AListener, AEvent>::unregisterListener;
using ListenerBus<AListener, AEvent>::sendEvent;
using ListenerBus<BListener, BEvent>::registerListener;
using ListenerBus<BListener, BEvent>::unregisterListener;
using ListenerBus<BListener, BEvent>::sendEvent;
// need to replicate above for every base class for name resolution
};
// construct as
EventBus bus;
The registerListener(), unregisterListener(), and sendEvent() member functions are all non-virtual since you don't want them to be over-ridden by EventBus (which will then be affected by the hiding rule).
In addition to assuming no inheritance relationships between any Listener or Event classes, both approaches above assume the Listener and Event classes are all distinct types (i.e. no Listener class or Event class listed more than once). The most likely outcome, if you break that assumption, will be that calls of some of the member functions will become ambiguous.

Double partial template specialization for a class

I've stumbled upon a little problem with a little code I'm doing while learning c++11/14. Basically I have a Debugging class which I want to handle all the message printing. Most debugging/logging classes have log levels of sorts, but I want to use a flag for each message I have.
For that I have a little enum where I define my flags and their values:
enum DebugFlag {
Flag1 = 0,
Flag2 = 1,
Flag3 = 2
};
Aditionally, I have a Debugging class, which I've managed to specialize for Flag types and it works pretty well.
template<DebugFlag T>
class Debug {
public:
template <typename U>
static void print(U &&arg) {}
};
template <>
class Debug<static_cast<DebugFlag>(1)> {
public:
static void print(std::string &&message) {
std::cerr<<message<<"\n";
}
static void print(std::ostream &message) {
std::cerr<<DebugStream()().str()<<"\n";
DebugStream()().str("");
DebugStream()().clear();
}
static void print(std::string &message) {
std::cerr<<message<<"\n";
}
};
To call this class, I use a call like:
Debug<Flag1>::print("Message\n"); // should not do anything with Flag1 compiled to 0 value
Debug<Flag2>::print("Message\n"); // should work
Now I wanted to expand this class to also take bool values, so calls like this will work:
Debug< Flag2<2 >::print("Message\n"); // should not do anything with Flag1 compiled to 2 value
Debug< Flag2<1 >::print("Message\n"); // should work
The problem is I need a second partial specialization for my Debug class, that is bool, and I can't figure exactly what the syntax is for this.
This is the closest I've come to it, but still can't figure out what I'm doing wrong or if it's possible without making a secondary class and changing the way I want my call to look like: http://cpp.sh/6yemn
I don't understand exactly how you want to be able to use your class, but here's something that works.
template <typename T, T v = T()>
class Debug {};
template <>
class Debug<Flag, Flag2> {
public:
void f() { std::cout<<"This is good\n"; }
};
template <>
class Debug<bool, true> {
public:
void f() { std::cout<<"This is good too\n"; }
};
The problem is that you need to specify the type : whether you want to use a bool or a Flag, and then the value. You can instantiate the class like so :
Debug<bool, true> trueDebug;
Debug<Flag, Flag2> flag2Debug;
Other instances won't have the f function unless you add a specialization. For example :
template <Flag v>
class Debug<Flag, v> {
public:
void f() { std::cout<<"This is bad\n"; }
};
Live example

Templated Function results in Circular Inclusion

I have a tricky circular inclusion issue that I dont know how to solve. To sum up:
IApp inherits from Component
Component implements a templated function in its header file that uses IApp::registerForEvent
What technique or method can I use to fix/avoid this circular inclusion?
class Component;
class IApp;
class Component
{
IApp* app;
// Error: Invalid use of incomplete type 'class IApp'
template<typename T>
void registerEvent(const int& evtId, Status (T::*func) (int))
{
auto res = std::bind(func, (T*)this, std::placeholders::_1);
app->registerForEvent(evtId);
}
};
class IApp : public Component
{
public:
void registerForEvent(const int& evtId)
{
printf("IApp::registerForEvent\n");
// ...
}
};
Define registerEvent after IApp.
class IApp;
class Component
{
IApp* app;
template<typename T>
void registerEvent(const int& evtId, Status (T::*func) (int));
};
class IApp : public Component {
...
};
template <typename T>
Component::registerEvent(const int& evtId, Status (T::*func) (int)) {
auto res = std::bind(func, (T*)this, std::placeholders::_1);
app->registerForEvent(evtId);
}
If need be, also define A::registerEvent after Component::registerEvent.
You are trying to use a derived class in it's base class, which doesn't seem like a good design approach to me. I would suggest moving it to some other class, which both classes have access to.
Your are aggregating a Derived class object. Your may thus solve the circular dependence with the curiously recurring template pattern?
template <typename Aggregated>
class Component
{
Aggregated* app;
template<typename T>
void registerEvent(const int& evtId, Status (T::*func) (int))
{
auto res = std::bind(func, (T*)this, std::placeholders::_1);
app->registerForEvent(evtId);
}
};
class IApp : public Component<IApp>
{
public:
void registerForEvent(const int& evtId)
{
printf("IApp::registerForEvent\n");
// ...
}
};
Still, it is not clear to me what you are trying to do. For one you assume the function passed Component::registerEvent is a member of Component (you bind to (T*)this) whilst delegating the Event ID to the aggregated IApp. To me it seems rethinking your design may solve also the circular dependence problem?

Derived from template class?

I'm trying to use the following code, but can't get it to complete.
Can anyone see the problem?
class IResourceJob
{
public:
virtual ~IResourceJob() {}
virtual void execute() = 0;
};
template<typename T>
class ResourceJob : public IResourceJob
{
public:
void execute()
{
static_assert(false, "Specialised ResourceJob<T> not defined!");
}
};
template<>
class ResourceJob<int>
{
public:
void execute()
{
// test.
}
};
The following usage gives a compile error:
IResourceJob* job = new ResourceJob<int>;
Thanks!
The compiler gives an error for any template that can never be instantiated. For your member function of the class template (i assume you mean static_assert), that is true, so the compiler is in right to give you a diagnostic.
You want to make the condition depend on T and cleverly make it always evaluate to false when instantiated. For example like
template<typename T>
struct always_false : std::false_type {};
template<typename T>
class ResourceJob : public IResourceJob
{
public:
void execute()
{
static_assert(always_false<T>::value,
"Specialised ResourceJob<T> not defined!");
}
};
Since the compiler cannot know whether the user will put a specialization of always_false (which you won't, of course), it cannot early-reject the template anymore.
I also doubt that you wanted to put the static_assert into execute, since your error message indicates that ResourceJob as a whole needs to be specialized. So put the static_assert outside of the member function into the class body. If you don't want the user to specialize the whole template, but only the member function, the user instead needs to say
// either "inline" and in the header, or not "inline" and in the .cpp file, but then
// put this into the header: template<> void ResourceJob<int>::execute();
template<> inline void ResourceJob<int>::execute() {
}
This will provide an alternative definition of execute which will be used by the template if T is int.
IResourceJob* job = new ResourceJob<int>;
fails because the class ResourceJob<int> is not derived from from IResourceJob.
The code should be
template<>
class ResourceJob<int> : public IResourceJob
{
public:
void execute()
{
// test.
}
};
You need to derive the template specialization as well, as in:
template<>
class ResourceJob<int> : public IResourceJob
{ /* ... */ };

How to code inlineable mutual abstracion in C++?

Example first:
template <class HashingSolution>
struct State : public HashingSolution {
void Update(int idx, int val) {
UpdateHash(idx, val);
}
int GetState(int idx) {
return ...;
}
};
struct DummyHashingSolution {
void UpdateHash(int idx, int val) {}
void RecalcHash() {}
};
struct MyHashingSolution {
void UpdateHash(int idx, int val) {
...
}
void RecalcHash() {
...
UpdateHash(idx, GetState(idx)); // Problem: no acces to GetState function, can't do recursive application of templates
...
}
};
In this example I can pass MyHashingSolution to State class so State have access to HashingSolution's methods, but HashingSolution can't call GetState. Is it possible to work around this?
This is in the deepest loop. virtual function here drops the performance by more than 25%.
Inlineing is crucial for me.
As jalf suggests in the comments, you probably want to use a variant of the Curiously Recurring Template Pattern (CRTP). That is, make MyHashingSolution a class template parametrised by the derived class:
template <typename D>
struct MyHashingSolution {
typedef D Derived;
void UpdateHash(int idx, int val) {
...
}
void RecalcHash() {
...
UpdateHash(idx, derived().GetState(idx));
...
}
private:
// Just for convenience
Derived& derived() { return *static_cast<Derived*>(this); }
};
In this case, because you want the derived State class to also be a template, you need to take the slightly unusual step of declaring State as a class template that takes a template template parameter:
template <template <class T> class HashingSolution>
struct State : public HashingSolution<State<HashingSolution> > {
typedef HashingSolution<State<HashingSolution> > Parent;
void Update(int idx, int val) {
Parent::UpdateHash(idx, val); // g++ requires "Parent::"
}
int GetState(int idx) {
return ...;
}
};
The key point is that, provided State inherits from HashingSolution<State<HashingSolution> >, Derived is a derived class of HashingSolution<State<HashingSolution> > so the static_cast<Derived*>(this) downcast in HashingSolution<State>::derived() compiles and works correctly. (If you mess up and derive State from HashingSolution<SomeOtherType> instead and then try something that involves a call to derived(), the compiler will complain as the requirements for static_cast<> are not met.)
Then declare the concrete State class you want to use like so:
typedef State<MyHashingSolution> MyState;
Unfortunately this solution has the side effect that you will need to change DummyHashingSolution (and any other such types) to templates that ignore their one template argument, in order to make them usable as template template arguments.
As a shot in the dark, considering the almost complete lack of information in the question (see comments): would templates be useful? They're often good for compile-time polymorphism.
To get any more potentially useful information, please explain the problem more. Look at the problem comments. Tell us why you know what micro-optimizations need to be made when you're still working on fundamental design. If there's anything non-mainstream about the compilation or execution environments, give us a few details.