Re: How to discover argument and result types from lambda for
constructing std::function?
On 2012-02-02 06:15, Frank Birbacher wrote:
-----BEGIN PGP SIGNED MESSAGE-----
I have a class template that contains a boost::function member
variable (shall be std::function in future, but gcc4.6 does not have
it.) The function depends on the template arguments of the class
template. For constructing an instance of the class template I added
a free function template that shall be able to discover the template
arguments---just like std::make_pair does.
The problem lies in an easy definition of a function template that
will accept a lambda type, deduce the argument and result types, and
construct the correct instantiation of the class template. I have
played around with decltype, but I'm not quite happy with my solution.
Is there any easier solution?
Some parts of your second overload look unnecessarily complicated to me.
Why shouldn't it be necessary to invoke the first overload on function
objects? Consider
template<typename F>
auto mkHolder(F&& f) ->
typename discover_f_type<decltype(&F::operator())>
::function_type
{
typedef discover_f_type<decltype(&F::operator())> D;
return typename D::function_type(std::forward<F>(f));
}
as an alternative. Further I see at least three things that could be
improved here:
a) Albeit rarely to be expected, there is no reason, why mkHolder could
no be called with an lvalue referring to a lambda closure. In this case
you have to ensure that you remove the reference from the deduced
effective parameter, e.g. like so:
template<typename F>
auto mkHolder(F&& f) ->
typename
discover_f_type<decltype(&std::remove_reference<F>::type::operator())>
::function_type
{
typedef
discover_f_type<decltype(&std::remove_reference<F>::type::operator())> D;
return typename D::function_type(std::forward<F>(f));
}
b) A lambda closure can be declared as mutable, with the effect of
having a non-const operator() overload instead. This means you should
add one further specialization of discover_f_type for the pattern Result
(T::*)(Arg).
c) I like to note that your first mkHolder overload only accepts rvalues
of boost::function, which is asymmetric to your mkHolder(F&&) overload.
I suggest to add one further overload for boost::function accepting
lvalues as well.
Is relying on&F::operator() fine for lambda types F?
Good question. The current wording seems to specify this quite
precisely, so it looks like a reasonable approach to me.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]