简体   繁体   English

使用std :: function的模板类型推导

[英]Template type deduction with std::function

I have discovered the following behaviour with std::function and type deduction, which was unexpected for me: 我用std::function和type deduction发现了以下行为,这对我来说意外:

#include <functional>

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

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

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

Both lines in main result in error: main中的两行都会导致错误:

no instance of function template "stdfunc_test" matches the argument list 没有函数模板“stdfunc_test”的实例与参数列表匹配

When attempting to compile in Visual Studio 2015. 尝试在Visual Studio 2015中编译时。

Why doesn't the type deduction deduct template type from the function type, and is there a workaround for it? 为什么类型扣除不会从函数类型中扣除模板类型,是否有解决方法?

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 你可以在这里试试吧: http//fiddle.jyt.io/github/d4ab355eb2ab7fc4cc0a48da261f0127

No implicit conversion is performed during template argument deduction, except: temp.deduct.call 在模板参数推导期间不执行隐式转换,除了: 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). 通常,演绎过程试图找到模板参数值,这些参数值将使推导出的A与A相同(在如上所述变换类型A之后)。 However, there are three cases that allow a difference: 但是,有三种情况可以产生差异:

  • If the original P is a reference type, the deduced A (ie, the type referred to by the reference) can be more cv-qualified than the transformed A. 如果原始P是引用类型,则推导出的A(即,引用所引用的类型)可以比转换后的A更具有cv限定。
  • 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]). 变换后的A可以是另一个指向成员类型的指针或指针,可以通过函数指针转换([conv.fctptr])和/或限定转换([conv.qual])将其转换为推导出的A.
  • 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. 如果P是一个类而P的形式为simple-template-id,则转换后的A可以是推导出的A的派生类。同样,如果P是指向simple-template-id形式的类的指针,变换A可以是指向由推导出的A指向的派生类的指针。

However, if the template parameter doesn't participate in template argument deduction, implicit conversion will be performed: ( temp.arg.explicit ) 但是,如果模板参数不参与模板参数推导,则将执行隐式转换:( 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. 如果参数类型不包含参与模板参数推导的模板参数,则将对函数参数执行隐式转换(Clause [conv])以将其转换为相应函数参数的类型。 [ 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM