Here is my code:
#include <stdio.h>
#include <utility>
#include <tuple>
template <typename Obj, typename Method, typename Args, size_t... Ns>
inline void DispatchToMethodImpl(const Obj& obj, Method method, Args&& args,
std::index_sequence<Ns...>) {
(obj->*method)(std::get<Ns>(std::forward<Args>(args))...);
}
template <typename Obj, typename Method, typename Args>
inline void DispatchToMethod(const Obj& obj, Method method, Args&& args) {
constexpr size_t size = std::tuple_size<std::decay_t<Args>>::value;
DispatchToMethodImpl(obj, method, std::forward<Args>(args),
std::make_index_sequence<size>());
}
class TaskEventBase {
public:
virtual void Run() = 0;
};
template <typename Obj, typename Method, typename Args>
class TaskEvent : public TaskEventBase {
public:
TaskEvent(Obj* obj, Method method, Args&& args) {
obj_ = obj;
method_ = method;
args_ = std::forward<Args>(args);
}
void Run() override { DispatchToMethod(obj_, method_, args_); }
private:
Obj* obj_;
Method method_;
Args args_;
};
int main() {
printf("event loop test start\n");
struct Foo {
int x;
int y;
int Add(int a, int b) {
printf("res is %d\n", a + b);
return a + b;
}
};
Foo foo;
DispatchToMethod(&foo, &Foo::Add, std::make_tuple(1, 2));
auto e = new TaskEvent(&foo, &Foo::Add, std::make_tuple(1, 2));
printf("event loop test end\n");
return 0;
}
Try build with: g++ -g -Wall -std=c++14 -o a test_template_args.cc
Then I get the following error:
test_template_args.cc:70:16: error: expected type-specifier before ‘TaskEvent’
auto e = new TaskEvent(&foo, &Foo::Add, std::make_tuple(1, 2));
I don't understand why DispatchToMethod function template works:
DispatchToMethod(&foo, &Foo::Add, std::make_tuple(1, 2));
But TaskEvent class template doesn't work:
auto e = new TaskEvent(&foo, &Foo::Add, std::make_tuple(1, 2));
Since C++17 your code works due to CTAD.
Until C++14, the code doesn't work because constructor of
TaskEventis non template function, so class template parameters cannot be deduced from the call parameters ofTaskEventconstructor, contrary toDispatchToMethodwhich is template function - allObj,MethodandArgsare deducible from passed arguments of function invocation.You can explicitly provide template parameters via template arguments list: