如何获取采用可调用对象来匹配类型的函数模板?
How to get function template taking invokables to match the types?
我有以下代码,旨在采用一个带有两个参数的通用函数对象和 return 一个函数对象,该函数对象以其他顺序对参数执行相同的操作。
#include <type_traits>
#include <functional>
template<typename Function, typename FirstIn
, typename SecondIn, typename std::enable_if<std::is_invocable<Function, FirstIn, SecondIn>::value>::type>
std::function<typename std::invoke_result<Function, FirstIn, SecondIn>::type(SecondIn, FirstIn)>
swapInput(Function f)
{
return[=](SecondIn b, FirstIn a) { return std::invoke(f, a, b); };
}
int main()
{
std::function<bool(std::string, int)> isLength = [](std::string s, int len) {return (s.size() == len); };
std::function<bool(int, std::string)> lengthIs =
swapInput<std::function<bool(std::string, int)>, std::string, int>(isLength);
}
这在分配 lengthIs
:
的行给出了以下编译器错误
Error C2783 'std::function<std::invoke_result<Function,FirstIn,SecondIn>::type(SecondIn,FirstIn)> swapInput(Function)'
: could not deduce template argument for '__formal'
Error C2672 'swapInput': no matching overloaded function found
我正在使用 Visual Studio 19 设置为 C++17。
您对 std::enable_if
的用法是错误的。你需要
template<typename Function, typename FirstIn, typename SecondIn
, typename = std::enable_if_t<
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
std::is_invocable_v<Function, FirstIn, SecondIn>
>
>
std::function<std::invoke_result_t<Function, FirstIn, SecondIn>(SecondIn, FirstIn)>
swapInput(Function f)
{
return [=](SecondIn b, FirstIn a) { return std::invoke(f, a, b); };
}
建议:
由于您使用的是 c++17,我建议 auto
return 用于 swapInput
。
更进一步,如果您重新排列函数模板参数,则不需要在函数调用时使用冗长的显式 std::function<bool(std::string, int)>
。
使用if constexpr
,代码更易读:
结合以上建议:
template<typename FirstIn, typename SecondIn, typename Function>
auto swapInput(Function f)
{
if constexpr (std::is_invocable_v<Function, FirstIn, SecondIn >)
return [=](SecondIn b, FirstIn a) { return std::invoke(f, a, b); };
}
现在函数调用是
std::function<bool(int, std::string)> lengthIs
= swapInput<std::string, int>(isLength);
我有以下代码,旨在采用一个带有两个参数的通用函数对象和 return 一个函数对象,该函数对象以其他顺序对参数执行相同的操作。
#include <type_traits>
#include <functional>
template<typename Function, typename FirstIn
, typename SecondIn, typename std::enable_if<std::is_invocable<Function, FirstIn, SecondIn>::value>::type>
std::function<typename std::invoke_result<Function, FirstIn, SecondIn>::type(SecondIn, FirstIn)>
swapInput(Function f)
{
return[=](SecondIn b, FirstIn a) { return std::invoke(f, a, b); };
}
int main()
{
std::function<bool(std::string, int)> isLength = [](std::string s, int len) {return (s.size() == len); };
std::function<bool(int, std::string)> lengthIs =
swapInput<std::function<bool(std::string, int)>, std::string, int>(isLength);
}
这在分配 lengthIs
:
Error C2783 'std::function<std::invoke_result<Function,FirstIn,SecondIn>::type(SecondIn,FirstIn)> swapInput(Function)'
: could not deduce template argument for '__formal'
Error C2672 'swapInput': no matching overloaded function found
我正在使用 Visual Studio 19 设置为 C++17。
您对 std::enable_if
的用法是错误的。你需要
template<typename Function, typename FirstIn, typename SecondIn
, typename = std::enable_if_t<
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
std::is_invocable_v<Function, FirstIn, SecondIn>
>
>
std::function<std::invoke_result_t<Function, FirstIn, SecondIn>(SecondIn, FirstIn)>
swapInput(Function f)
{
return [=](SecondIn b, FirstIn a) { return std::invoke(f, a, b); };
}
建议:
由于您使用的是 c++17,我建议
auto
return 用于swapInput
。更进一步,如果您重新排列函数模板参数,则不需要在函数调用时使用冗长的显式
std::function<bool(std::string, int)>
。使用
if constexpr
,代码更易读:
结合以上建议:
template<typename FirstIn, typename SecondIn, typename Function>
auto swapInput(Function f)
{
if constexpr (std::is_invocable_v<Function, FirstIn, SecondIn >)
return [=](SecondIn b, FirstIn a) { return std::invoke(f, a, b); };
}
现在函数调用是
std::function<bool(int, std::string)> lengthIs
= swapInput<std::string, int>(isLength);