I am attempting to create a class template whose constructor(s) can take any kind of function as argument, that is, it takes a function pointer (which can be a member function pointer) and the corresponding function arguments. Additionally, there should be a static_assert that checks whether the function return type (taken from the function pointer) matches the class template parameter type. Thus, the code should look something like this:
template <class ReturnType>
struct Bar
{
template <class RetType, class ... ParamType>
Bar<ReturnType>(RetType (* func)(ParamType ...), ParamType && ... args) :
package_(std::bind(func, std::forward<ParamType>(args) ...)),
function_([this] { package_(); }),
future_(package_.get_future())
{
static_assert(std::is_same<ReturnType, RetType>::value,
"Type mismatch between class parameter type and constructor parameter type");
}
template <class RetType, class ObjType, class ... ParamType>
Bar<ReturnType>(RetType (ObjType::* func)(ParamType ...), ObjType * obj, ParamType && ... args) :
package_(std::bind(func, obj, std::forward<ParamType>(args) ...)),
function_([this] { package_(); }),
future_(package_.get_future())
{
static_assert(std::is_same<ReturnType, RetType>::value,
"Type mismatch between class parameter type and constructor parameter type");
}
std::packaged_task<ReturnType()> package_;
std::function<void()> function_;
std::future<ReturnType> future_;
};
The idea is that the code compiles for these situations, and allows for Bar::function_ to be called (through the function call operator) without errors:
struct Foo
{
int foo(int i) {
return i;
}
int foo() {
return 1;
}
};
int foo(int i)
{
return i;
}
int foo()
{
return 1;
}
int main()
{
Foo f = Foo();
Bar<int> b1(&Foo::foo, &f, 1);
Bar<int> b2(&Foo::foo, &f);
Bar<int> b3(foo, 1);
Bar<int> b4(foo);
return 0;
}
Unfortunately, I have close to zero experience with template metaprogramming, and even though I have ran over several questions here in SO, and attempted several ways of solving my problem, such as using a more generalized approach to the constructor
template <class RetType, class ... ParamType>
Bar<ReturnType>(RetType func, ParamType && ... args)
and combining it with type_traits to determine the return type), I have yet to find a way to make this work. What changes can I do to the constructor(s) that allow this functionality?
Aucun commentaire:
Enregistrer un commentaire