Template that calls member function on argument - c++

I have some code that creates several listeners. Thus I was thinking about adding a template that calls the notify on different types of listeners. However I am not sure how to call the member function (which all have different arguments) in a template. I am using C++17.
template <class T>
void notifyListeners(std::vector<T*> listeners, std::function<???> memfunc) {
// perhaps add a compile time check to see if memfunc exists
for (auto& listener : listeners) {
listener->memfunc();
}
}
For example I have two classes of listeners :
class IFooListener {
void Foo(int, double, std::string);
}
class IBarListener {
void Bar(std::string, std::string)
}
std::vector<IFooListeners*> fooListeners;
std::vector<IBarListeners*> barListeners;
I would like to be able to do something like this:
notifyListeners(fooListeners, &IFooListener::Foo, 1, 2.0, "Bla");
notifyListeners(barListeners, &IBarListener::Bar, "one", "two");
How can this be done?

template <class T, typename F, typename... Args>
void notifyListeners(std::vector<T*> listeners, F f, Args&&... args) {
for (auto& listener : listeners) {
(listener->*f)(std::forward<Args>(args)...);
}
}
Demo

Not sure if I understand problem correctly. Here is my first approach using C++17:
template <typename T>
class Notifier {
public:
void addObserver(T observer)
{
mObservers.emplace_back(observer);
}
template<auto f, typename...Ts>
void notify(Ts&&...args) const
{
for(auto& p : mObservers)
{
notifyOne<f>(p, std::forward<Ts>(args)...);
}
}
private:
template<auto f, typename...Ts>
static void notifyOne(T p, Ts&&...args)
{
(p->*f)(std::forward<Ts>(args)...);
}
private:
std::vector<T> mObservers;
};
Here as some tests proving it works.
Disclaimer: I used perfect forwarding, but in case same argument may be used multiple times this is not best choice. I think some protection form moving argument values should be added.
Here is C++11 version with function pointer pass as function argument.
Edit: Got another improvement. Now this template is able to handle std::weak_ptr: demo

Related

C++ template type circularity and non-template pointer to template instance

For reference, here is the minimal example : http://coliru.stacked-crooked.com/a/75354688a0a6af64
In this example, I have a single problem of template type circularity that, in my view, could be solved in two ways :
make the Controller a template class and the Event member pointer a non-template pointer to a template class instance (but how ?)
use std::any or something like it to keep the Controller class non-template (like is shown in the example, but doesn't compile)
What is the best way to make this work in a cleanly ?
EDIT : link updated
You cannot fully type erase functor which accept template argument.
But if you know the subset of template argument to handle, std::any/ std::variant might help:
In your case non-supported event do no-op, so "your" controller:
template <typename ... Modules>
class Controller {
public:
std::tuple<Modules...> modules;
template<typename evt_t>
void emit(evt_t event) {
std::apply([this](auto&&... args) {((args.dispatch(Event<evt_t>{event, this})), ...);}, modules);
}
Controller(std::tuple<Modules...> _modules) : modules{_modules}{}
};
becomes
class Controller {
std::function<void(std::any)> func;
public:
template<typename evt_t>
void emit(evt_t event) {
func(event);
}
template <typename ... Modules, typename EventTags>
Controller(std::tuple<Modules...> tmodules, EventTags event_tags)
{
func = [=, this](std::any any_ev){
auto f = [&, this](auto tag){
using EventType = typename decltype(tag)::type;
if (auto* ev = std::any_cast<EventType>(&any_ev)) {
std::apply([=, this](auto&&... modules) {((modules.dispatch(Event<EventType>{*ev, this})), ...);}, tmodules);
}
};
std::apply([&f](auto... tags){ (f(tags), ...); }, event_tags);
};
}
};
Demo
The issue seems to be not what you think it is.
std::vector<std::any> modules;
//...
for(auto mod : modules) { mod.dispatch(Event{event, this}); } // should probably use an algorithm here
First you cannot iterate a tuple like that. Secondly any doesn't have a dispatch method.

variadic typedef that can be used in function signature

Basically I just want to wrap any callable object and their arguments in a Task obj that can be called later. Here are the code that come to mind:
Lets say all those callable type have a member type can be seemed as if they are defined like this:
template<typename TReturn, typename...TArgs>
struct SomeFunction{
using ArgTypes = TArgs; // won't compile of course
}
And the Task Template can be defined like this:
template<typename TFunction>
class Task {
public:
Task(TFunction fun, typename TFunction::ArgTypes...args) // won't compile
: fun_(fun), args_(args){}
void operator()()
{
fun_(args_...); // won't compile: workaround 1
}
private:
typename TFunction::ArgTypes... args_; // won't compile: workaround 2
TFunction fun_;
};
The problem lies in the definition of Task's constructor. Is there any way to achieve it? Of course I can define it as a template constructor:
template<typename...TArgs>
Task(TFunction fun, TArgs...args)
But in this way the compiler won't know that the TArgs are the same as TFunction::ArgTypes. Consequently, the error messages are ridiculous when wrong arguments passed to it.
workaround 1 : C++ How to store a parameter pack as a variable
workaround 2 : Is it possible to "store" a template parameter pack without expanding it?
You could use a std::tuple<TArgs...> to store the arguments and unpack them in the call-operator. If you want to define TArgs in some way in a function type, you should define them as a tuple there:
template<typename TReturn, typename...TArgs>
struct SomeFunction{
using ArgTypesTuple = std::tuple<TArgs...>;
// ^^^^^^^^^^
}
But nevertheless, I think it's not worth the effort to save the arguments in your Task object with a lot of boilerplate code... The call operator would look somewhat ugly to reconstruct / unpack the arguments from the tuple to a list of arguments.
The much easier solution is to make a lambda which captures the arguments at construction time of your Task object, which doesn't even need to be a template anymore:
class Task {
public:
template<typename TFunction, typename ...ArgTypes>
Task(TFunction fun, ArgTypes... args)
: fun_([=]{ fun(args...); }) {}
void operator()()
{
fun_();
}
private:
std::function<void()> fun_;
};
What you may do with some changes:
template <typename TReturn, typename...TArgs>
struct SomeFunction{
using ReturnType = TReturn;
using ArgTypes = std::tuple<TArgs...>;
};
For Task:
template <typename TFunction, typename TupleArg = typename TFunction::ArgTypes>
class Task;
template <typename TFunction, typename... TArgs>
class Task<TFunction, std::tuple<TArgs...>>
{
public:
Task(TFunction fun, TArgs...args) : fun_(fun), args_(args...) {}
void operator()()
{
call(make_index_sequence<sizeof...(TArgs)>{});
}
private:
template <std::size_t ... Is>
void call(index_sequence<Is...>)
{
fun_(std::get<Is>(args_)...);
}
private:
TFunction fun_;
std::tuple<TArgs...> args_;
};
Live example

How to create a variadic template function with `std::function` as a function parameter?

How can I create a variadic template function with std::function as a function parameter that accepts a variadic number of arguments? I tried to reduce the problem to a MWE:
#include <functional>
template <class T> void run(std::function<void(T *)> fun, T *obj) { fun(obj); }
template <class T, class... Args>
void run_variadic(std::function<void(T *, Args...)> fun, T *obj, Args... args) {
fun(obj, args...);
}
struct Foo {
void bar() {}
};
int main() {
Foo foo;
std::function<void(Foo *)> fun = &Foo::bar;
run(fun, &foo); // works
run<Foo>(&Foo::bar, &foo); // works
run_variadic(fun, &foo); // works
run_variadic<Foo>(&Foo::bar, &foo); // does not compile
}
It seems like the mere presence of the variadic template parameter in run_variadic makes it impossible to directly call it with a member function pointer. clang's error message is as follows:
main.cpp:21:3: error: no matching function for call to 'run_variadic'
run_variadic<Foo>(&Foo::bar, &foo); // does not compile
^~~~~~~~~~~~~~~~~
main.cpp:6:6: note: candidate template ignored: could not match 'function<void (Foo *, type-parameter-0-1...)>' against 'void (Foo::*)()'
void run_variadic(std::function<void(T *, Args...)> fun, T *obj, Args&&... args) {
^
1 error generated.
Any suggestions on how I can fix run_variadic so that I do not have to go through the extra std::function object?
Background
I have a class hierarchy as
template <class T> class Abstract { ... };
class UnrelatedStuff { ... };
class Derived : public Abstract<UnrelatedStuff> { ... };
There are multiple Derived classes that all have to implement one or more methods to loop over a range of elements. The loop looks something like
#pragma omp parallel for
for (ZFSId i = begin; i != end; ++i) {
callMemFun(i, and, other, args);
}
All loops should be OpenMP-accelerated. I want the accelerator stuff factored out and not repeated in each method of Derived that uses a loop, so that I only have to change one place if e.g. OpenMP would switch to OpenACC.
Thus I am looking for a way to put the loop (and its decoration) in its own function. Moving it to the Abstract base class is not an option either, since the loops are performance-critical and I cannot have an abstract function call in each loop iteration.
You are almost always certainly better off abstracting away the function object:
template <class Functor, class... Args>
void run(Functor&& f, Args&&... args) {
f(std::forward<Args>(args)...);
}
This allows you to do the right thing at call site:
// function object is a lambda that binds to a member function:
run([&](auto... args) { foo.bar(args...); } /*, bar takes no args...*/);
I prefer a lambda to std::function or std::bind but you can also use those if they are already available:
run(std::function<void(Foo *)>{&Foo::bar}, &foo);
run(std::bind(&Foo::bar, &foo));
run(std::mem_fn(&Foo::bar), foo);
I provide a full example program below.
You have now edited the question with new information regarding what you are trying to do.
I'm pretty sure that you don't want to do this, since the OpenMP/OpenACC pragmas like parallel for usually require extra annotations for delivering reasonable performance, and they depend on what you are exactly trying to do at call site.
Still, if you really really want to go this route you can write your own for_each algorithm and dispatch according to an ExecutionAgent (see N3874 and N3731). If OpenMP, TBB, OpenACC parallel task are too slow, you can also easily provide overloads based on e.g. an ExecutionPolicy like this:
template<class RandomAccessRange, class Functor,
class ExecutionPolicy = execution::serial_t>
void for_each(RandomAccessRange&& r, Functor&& f,
ExecutionPolicy&& ex = ExecutionPolicy{}) {
detail::for_each_(std::forward<RandomAccessRange>(r),
std::forward<Functor>(f),
std::forward<ExecutionPolicy>(ex));
}
And then you can implement overloads of for_each_ for each execution policy, e.g.:
namespace detail {
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::serial_t) {
boost::for_each(std::forward<RandomAccessRange>(r), std::forward<Functor>(f));
}
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::openmp_t) {
#pragma omp parallel for
for (auto&& v : r) { f(v); }
}
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::openacc_t) {
#pragma acc parallel for
for (auto&& v : r) { f(v); }
}
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::tbb_t) {
tbb::parallel_for_each(std::begin(std::forward<RandomAccessRange>(r)),
std::end(std::forward<RandomAccessRange>(r)),
std::forward<Functor>(f));
}
} // namespace detail
Note that the ExecutionPolicy is just a tag, i.e.:
namespace execution {
struct serial_t {}; static const constexpr serial_t serial{};
struct openmp_t {}; static const constexpr openmp_t openmp{};
struct openacc_t {}; static const constexpr openacc_t openacc{};
struct tbb_t {}; static const constexpr tbb_t tbb{};
} // namespace execution
This will at least give you an efficient TBB backend even tho the OpenMP/OpenACC performance will be mediocre at best. You can take a look at the parallel implementation of libstdc++ where they use OpenMP. Their for_each algorithm is over 1000 lines of code and uses work-stealing.
Full example program:
#include <functional>
template <class Functor, class... Args>
void run(Functor&& f, Args&&... args) {
f(std::forward<Args>(args)...);
}
struct Foo { void bar() {} };
int main() {
Foo foo;
run([&](auto... args) { foo.bar(args...); } /*, bar takes no args*/);
run(std::function<void(Foo *)>{ &Foo::bar}, &foo);
run(std::bind(&Foo::bar, &foo));
run(std::mem_fn(&Foo::bar), foo);
}
To answer your comment on the previous answer, that answer can be adapted to support pointers to member functions in the way that you've asked for. The previous answer already works for all callable objects, but not directly with a pointer to member function because those are not callable with the usual f(args) syntax. The following version uses tag dispatch to distinguish between pointers to member functions and traditional callable objects, applying the call syntax appropriate to each case.
template <class Functor, class... Args>
void run_helper(std::false_type, Functor f, Args&&... args)
{
f(std::forward<Args>(args)...);
}
template <class Functor, class Arg0, class... Args>
void run_helper(std::true_type, Functor f, Arg0&& arg0, Args&&... args)
{
(std::forward<Arg0>(arg0).*f)(std::forward<Args>(args)...);
}
template <class Functor, class... Args>
void run(Functor f, Args&&... args)
{
run_helper(typename std::is_member_pointer<Functor>::type(),
f, std::forward<Args>(args)...);
}
This can be used in all the same ways as the previous answer could, but also supports directly passing in a pointer to member function:
run(&Foo::bar, foo);
It even works with overloaded member functions and member functions which are templates, if you explicitly instantiate the run template to bind to a particular overloaded function or function template instantiation.
Live example: http://ideone.com/vsBS4H

C++ : create custom function dispatcher from variadic template

I have some functions that read various types from serialized data, eg:
class DataDeserializer
{
int getInt();
std::string getString();
MyClass getMyClass();
}
I then have various callback functions that take arbitrary parameters, eg:
void callbackA (int, int, int);
void callbackB (int, std::string);
void callbackC (std::string, int, MyClass, int);
I want to call the various callbacks with arguments read from the deserialized data stream.
What I would like is to automate the boilerplate code as much as possible.
I was thinking maybe I could use templates. If I had some sort of Dispatcher
class, eg:
template <SOMETHING??> class Dispatcher
{
void dispatch()
{
// ????
}
SOMEFUNCTIONTYPE callback;
DataDeserializer myDeserializer;
};
Then declare various specific dispatchers:
Dispatcher<int,int,int> myDispatcherA (deserializer, callbackA);
Dispatcher<int,std::string> myDispatcherB (deserializer, callbackB);
Dispatcher<std::string,int,MyClass,int> myDispatcherC (deserializer, callbackC);
Then when I want to dispatch, I just call:
myDispatcherB.dispatch();
which underneath would expand to something like this:
void dispatch()
{
callback (myDeserializer.getString(), myDeserializer.getInt(), myDeserializer.getMyClass(), myDeserializer.getInt());
}
Is this possible with C++11 variadic templates? I've read up a little on them, and it seems recursion is used a lot.
I have done something similar for my stream_function class. The basic idea is that you pass a type to a function template, which does The Right Thing™, and expand that call:
callback(magic<Args>(/* sth */)...);
However, if your functions aren't pure and modify some state, and as such have the requirement that they need to be called in the correct order, you have to force that order with some tricks.
If you're using Clang, this is rather easy, as it forces left-to-right evaluation for braced-init-lists. This allows you to just use a small helper type
struct invoker{
template<class F, class... Args>
invoker(F&& f, Args&&... args){ f(std::forward<Args>(args)...); }
};
and then do
invoker{ callback, magic<Args>(/* sth */)... };
Unfortunately, GCC doesn't yet implement this feature, so one needs to resort to manual order-enforcement. This can be done with a small helper struct which is just a type-list, but allows one to do some useful things:
see when the pack is empty (types<>), and
process Args in a head-then-tail recursive fashion
template<class...> struct types{};
template<class... Args>
struct dispatcher{
std::function<void(Args...)> f;
void call(){ _call(types<Args...>{}); }
private:
// take head, produce value from it, pass after other values
template<class Head, class... Tail, class... Vs>
void _call(types<Head, Tail...>, Vs&&... vs){
_call(types<Tail...>{}, std::forward<Vs>(vs)..., get_value<Head>());
}
// no more values to produce, forward to callback function
template<class... Vs>
void _call(types<>, Vs&&... vs){ f(std::forward<Vs>(vs)...); }
};
Live example.
Something like this can help you
template<typename T>
T get_value(Deserializer&);
template<>
int get_value(Deserializer& d)
{
return d.getInt();
}
template<>
std::string get_value(Deserializer& d)
{
return d.getString();
}
template<typename... Args>
class Dispatcher
{
public:
template<typename Functor>
Dispatcher(Deserializer& d, const Functor& cb) : myDeserializer(d), callback(cb)
{
}
void dispatch()
{
callback(get_value<Args>(myDeserializer)...);
}
private:
std::function<void(Args...)> callback;
Deserializer myDeserializer;
};
Live example

Passing an arbitrary lambda expression to a function?

I have a pretty exotic problem, since I am trying to create some sort of a compiler...
I want to pass a lambda expression to a templated function like this:
template<class T>
delegate<T>* bind(std::function<T> func)
{
return nullptr;
}
So that I can now call
bind([&](int a) { // do something });
... So normally, this wouldn't be a problem, since std::function is able to capture a lambda. But here the problem is that (let's assume) I don't know or don't want to provide the info about what "T" is exactly. It could be any function signature you could also insert into std::function<>...
I also need to pass this "inferred" signature back to the "delegate" class I want to return and that delegate class needs to be a pointer to class...
For now I have come up with this:
template<class T>
struct delegate : public std::function<T>
{
delegate(const std::function<T>& func) : std::function<T>(func) { }
delegate(const delegate<T>& func) { }
};
template<class T>
delegate<T>* bind(std::function<T>&& func)
{
return new delegate<T>(std::forward<std::function<T>>(func));
}
But the above example of a call to "bind" fails with "failed template argument deduction". How can I get this to work without having to specify the "T" parameter explicitly when calling "bind" (then it works, at least)?
Since in theory my compiler has all the info to workaround this issue, I could just insert the instance of "T", but this would make the generated code unnecessarily convoluted.
BTW, I am using the lastest Clang compiler.
Here is the final solution:
template<typename T> struct get_signature;
template<typename Mem, typename Ret, typename... Args> struct get_signature<Ret(Mem::*)(Args...) const> {
typedef Ret type(Args...);
};
template<class T>
delegate<typename get_signature<decltype(&T::operator())>::type>* bind(T func)
{
return nullptr;
}
Be aware that you may need to adjust the "const" modifiers to your needs.
First, you have completely screwed up your rvalue references. Your forwarding does not work at all.
Secondly, that's impossible in some cases.. For some function objects, you could infer the signature by taking the member function pointer to operator() and inspecting it's signature. But for others, they will be overloaded and it will not work.
template<typename T> struct get_signature;
template<typename Mem, typename Ret, typename... Args>
struct get_signature<Ret(Mem::*)(Args...)> {
typedef Ret(Args...) type;
};
template<class T>
delegate<typename get_signature<&T::operator()>::type>* bind(T func)
{
return nullptr;
}
Thirdly, std::bind?