c++ - Deducing template parameter from functor argument type -
this question has answer here:
i have following code meant accept qt qvariant , apply functor if variant contains value:
template<typename t, typename functor> inline qvariant map(const qvariant& v, functor f) { return v.isvalid() ? qvariant{f(qvariant_cast<t>(v))} : v; }
my problem compiler cannot deduce type of t when invoke function as
map(somefuncreturningqvariant(), [](const qbytearray& array) -> qstring { return array.tostring(); });
the compiler complains (cleaned original error, has longer type names):
error: no matching function call `map(qvariant, <lambda(const qbytearray&)>)` note: candidate is: template<class t, class functor> qvariant map(const qvariant&, functor). note: template argument deduction/substitution failed: couldn't deduce template parameter 't'
this because qvariant erases type of object contains @ runtime. (it still knows internally, boost::any
, , qvariant_cast<t>()
gets original object back).
how can capture type of variable passed functor
, use elsewhere? alternatively, how can specify functor
takes parameter of type t
? (i suspect these same question, or @ least have same answer.)
note approach works fine std::optional
, because types not erased:
using std::experimental::optional; template<typename t, typename functor> inline auto map(const optional<t>& v, functor f) -> optional<decltype(f(*v))> { return v ? optional<decltype(f(*v))>{f(*v)} : v; }
also note qvariant code works fine if manually specify type:
map<qbytearray>(somefuncreturningqvariant(), [](const qbytearray& array) -> qstring { return array.tostring(); });
but of course, uglier.
basically want is: given functor, f
, identify decayed type of first argument.
to end, need function_traits
, can do:
template <typename f> using first_arg = std::decay_t<typename function_traits<f>::template arg<0>::type>;
which use:
template<typename functor> inline qvariant map(const qvariant& v, functor f) { using t = first_arg<functor>; return v.isvalid() ? qvariant{f(qvariant_cast<t>(v))} : v; }
Comments
Post a Comment