patterncppMinor
Factory template method for generalized functors
Viewed 0 times
generalizedtemplatemethodfactoryfunctorsfor
Problem
(A quick note on terminology: I use 'generalized functor' to refer to a functor that can be initialized from any callable entity, similar to the definition from Alexandrescu's Modern C++ Design. I use 'generic functor' to refer to functors in the general C++ sense, meaning anything which implements
I'm working on a factory for generalized functors in C++11. The functor's interface looks like this:
Please note that this is only a stub, and not part of the code I would like to be reviewed.
My attempted contribution is a factory method,
```
bool test() {
bool success = true;
// C-style function
auto f1 = make_functor(mult);
success &= ( f1(2, 3) == 6 );
// C-style function pointer
int(*pf)(int, int) = mult;
auto f2 = make_functor(pf);
success &= ( f2(3, 3) == 9 );
// Generic functor with overloaded operator()
doubler d;
auto f3 = make_functor(d);
success &= ( f3(2) == 4 );
// Member function pointer
container c;
auto f4 = make_functor(c, &container::triple);
success &= ( f4(4) == 12 );
// Just making sure none of the above breaks the copy-ct
operator())I'm working on a factory for generalized functors in C++11. The functor's interface looks like this:
// C-style function pointers, functors
template
struct functor {
call_type c;
functor(call_type c) : c(c) {}
res_type operator()(arg_types... args) { return c(args...); }
};
// Member function pointers
template
struct functor {
using call_type = res_type(T::*)(arg_types...);
T t;
call_type c;
functor(T t, call_type c) : t(t), c(c) {}
res_type operator()(arg_types... args) { return (t.*c)(args...); }
};Please note that this is only a stub, and not part of the code I would like to be reviewed.
My attempted contribution is a factory method,
make_functor, which should take care of deducing any template arguments where possible. In other cases (particularly overloaded functions) it should still allow users to specify the necessary template arguments directly. In practical terms, I would like it to satisfy the following testbed (also not part of the code I would like reviewed, though suggestions for extra testcases are always welcome):```
bool test() {
bool success = true;
// C-style function
auto f1 = make_functor(mult);
success &= ( f1(2, 3) == 6 );
// C-style function pointer
int(*pf)(int, int) = mult;
auto f2 = make_functor(pf);
success &= ( f2(3, 3) == 9 );
// Generic functor with overloaded operator()
doubler d;
auto f3 = make_functor(d);
success &= ( f3(2) == 4 );
// Member function pointer
container c;
auto f4 = make_functor(c, &container::triple);
success &= ( f4(4) == 12 );
// Just making sure none of the above breaks the copy-ct
Solution
Although you say the
could simply be:
Further, the arguments here should be passed by (universal) reference, and then forwarded:
The use of snake_case for template arguments is also highly unorthodox.
The final gripe is more of a question: what is this meant to be used for? If you already have a callable, why bother doing all this, instead of using it / passing it around directly. Between lambdas and
functor code is only a stub, there are still a number of things to improve that I'll point out. If you're using C++11, then I'd absolutely remove the res_type template parameter, as this can be deduced using decltype in every case here. For example:res_type operator()(arg_types... args) { return c(args...); }could simply be:
auto operator()(arg_type... args) -> decltype(c(args...))
{
return c(args...);
}Further, the arguments here should be passed by (universal) reference, and then forwarded:
auto operator()(arg_type&&... args) -> decltype(c(args...))
{
return c(std::forward(args)...);
}The use of snake_case for template arguments is also highly unorthodox.
The final gripe is more of a question: what is this meant to be used for? If you already have a callable, why bother doing all this, instead of using it / passing it around directly. Between lambdas and
std::function, I don't really see what this is adding.Code Snippets
res_type operator()(arg_types... args) { return c(args...); }auto operator()(arg_type... args) -> decltype(c(args...))
{
return c(args...);
}auto operator()(arg_type&&... args) -> decltype(c(args...))
{
return c(std::forward<arg_type>(args)...);
}Context
StackExchange Code Review Q#74874, answer score: 3
Revisions (0)
No revisions yet.