I have a toy example that I'd like to modify architecturally to remove type dependency of Processor
on EmitterT
:
#include <iostream>
#include <utility>
using namespace std;
struct Emitter {
void e(int) { cout << "emitting int\n";}
void e(double) { cout << "emitting double\n";}
void e(char*) { cout << "emitting char*\n";}
void e(const char*) { cout << "emitting const char*\n";}
};
template <typename EmitterT>
struct Processor {
Processor(EmitterT e) : e_{e} {}
template <typename T>
void process(T&& value) {
cout << "some processing... ";
e_(std::forward<T>(value));
}
EmitterT e_;
};
template<typename Emitter_>
Processor<Emitter_> makeProcessor(Emitter_ e) { return Processor<Emitter_>(e);}
int main() {
Emitter em;
auto p = makeProcessor([&em](auto v){em.e(v);});
p.process(1);
p.process("lol");
return 0;
}
Motivation
I'd like to decouple part responsible for utilizing results of processing from the processing itself. The Emitter
class structure is given to me, so I have to support overloaded functions.
I'd like to pass a lambda function to a processor that will use it. Kind of like a callback mechanism, however it must be a generic lambda, to support overloads.
What I've tried:
The example I wrote works, but it depends on Emitter
type as a template parameter. I don't like Processor
type to change based on Emitter
. It's also contagious, I have a real Processor
hierarchy and Emitter
spread like const
or worse.
After reading https://stackoverflow.com/a/17233649/1133179 I've tried playing with below struct as a member:
struct EmitterC {
template<typename T>
void operator()(T value) { }
};
But I cannot figure out a way to defer implementation of Emitter
after Processor
when using it as a normal parameter. It worked out with a forward declaration and a reference EmitterC&
but it supports one only Emitter definition. The only way I could come up with was to drop lambda, and make virtual overloads in EmitterC
for every type I expect in Emitter
and use it as a base class.
So, Is there a way to pass the (generic) lambda as a parameter, so that Processor
type doesn't depend on Emitter
?
I am restricted to c++14, but I am interested in more modern standards as well if the have better support.