Template type deduction with std::function

六眼飞鱼酱① 提交于 2019-11-30 19:43:44

No implicit conversion is performed during template argument deduction, except: temp.deduct.call

In general, the deduction process attempts to find template argument values that will make the deduced A identical to A (after the type A is transformed as described above). However, there are three cases that allow a difference:

  • If the original P is a reference type, the deduced A (i.e., the type referred to by the reference) can be more cv-qualified than the transformed A.
  • The transformed A can be another pointer or pointer to member type that can be converted to the deduced A via a function pointer conversion ([conv.fctptr]) and/or qualification conversion ([conv.qual]).
  • If P is a class and P has the form simple-template-id, then the transformed A can be a derived class of the deduced A. Likewise, if P is a pointer to a class of the form simple-template-id, the transformed A can be a pointer to a derived class pointed to by the deduced A.

However, if the template parameter doesn't participate in template argument deduction, implicit conversion will be performed: (temp.arg.explicit)

Implicit conversions (Clause [conv]) will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter type contains no template-parameters that participate in template argument deduction. [ Note: Template parameters do not participate in template argument deduction if they are explicitly specified.

So, if you explicitly specify the template argument, it should work:

stdfunc_test<int>([](int _) {return _ + 2;});
stdfunc_test<int>(test_func);

You can use templates to deduce the signature of functions and functors:

#include<functional>

template<class T>
struct AsFunction
    : public AsFunction<decltype(&T::operator())>
{};

template<class ReturnType, class... Args>
struct AsFunction<ReturnType(Args...)> {
  using type = std::function<ReturnType(Args...)>;
};

template<class ReturnType, class... Args>
struct AsFunction<ReturnType(*)(Args...)> {
  using type = std::function<ReturnType(Args...)>;
};


template<class Class, class ReturnType, class... Args>
struct AsFunction<ReturnType(Class::*)(Args...) const> {
  using type = std::function<ReturnType(Args...)>;
};

template<class F>
auto toFunction( F f ) -> typename AsFunction<F>::type {
  return {f};
}

template <typename T>
void stdfunc_test(std::function<T(T)> func) {};

int test_func(int arg)
{
    return arg + 2;
}


int main()
{

    stdfunc_test( toFunction([](int _) {return _ + 2;}) );
    stdfunc_test( toFunction(test_func) );
    return 0;
}

you can try it live here: http://fiddle.jyt.io/github/d4ab355eb2ab7fc4cc0a48da261f0127

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!