【问题标题】:How to get function template taking invokables to match the types?如何获取函数模板以匹配类型?
【发布时间】:2021-11-12 15:41:41
【问题描述】:

我有以下代码打算采用一个通用函数对象,该对象接受两个参数并返回一个函数对象,该函数对象以其他顺序对参数执行相同的操作。

#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  

我正在使用设置为 C++17 的 Visual Studio 19。

【问题讨论】:

    标签: c++ templates lambda c++17 function-templates


    【解决方案1】:

    您对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);  };
    }
    

    (See a Demo)


    建议

    • 由于您使用的是,我建议您使用autoswapInput 返回。

    • 更进一步,如果您重新排列函数模板参数,则在函数调用时不需要详细的显式 std::function&lt;bool(std::string, int)&gt;

    • 使用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);
    

    (See a Demo)

    【讨论】:

    • 非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多