【问题标题】:Overloading function template based on lambda arguments基于 lambda 参数重载函数模板
【发布时间】:2021-04-24 22:19:07
【问题描述】:

我正在尝试创建一个函数,调用者可以在其中传入带有一组已知参数的 lambda(返回类型可以是调用者想要的任何东西) 假设可能的 lambda 签名是

  1. T(小部件*)
  2. T (Widget2*)

我已经尝试了几件事,但我无法让它们中的任何一个工作

struct Widget2{
    int count = 0;
};

class Widget {
public:
template<typename Fn, typename T = std::invoke_result_t<Fn, Widget*>>
T doIt(Fn&& fn)
{
    return fn(_sibling);
}

template<typename Fn, typename T = std::invoke_result_t<Fn, Widget2*>>
T doIt(Fn&& fn)
{
    return fn(_other);
}

private: 
Widget* _sibling = nullptr;
Widget2* _other = nullptr;
};

我也尝试过这样做

template<typename Fn>
auto doIt(Fn&& fn)
{
    if (std::is_invocable_v<Fn, Widget*>)
        return fn(_sibling);
    else if (std::is_invocable_v<Fn, Widget2*>)
        return fn(_other);
}

编译器中的这段代码:https://wandbox.org/permlink/wMAuw5XXnc0zTjlk

我宁愿避免添加doItWidget1、doItWidget2等多个函数。

有没有一种方法可以让我根据传入的 lambda 参数重载函数?

【问题讨论】:

    标签: c++ templates overloading


    【解决方案1】:

    您可以使用enable_if 来消除错误的过载

    template<typename Fn, std::enable_if_t<std::is_invocable_v<Fn, Widget*>, int> = 0>
    auto doIt(Fn&& fn)
    {
        return fn(_sibling);
    }
    
    template<typename Fn, std::enable_if_t<std::is_invocable_v<Fn, Widget2*>, int> = 0>
    auto doIt(Fn&& fn)
    {
        return fn(_other);
    }
    

    请注意,您甚至不需要确定返回类型 T,只需使用 auto 即可。

    这是demo

    【讨论】:

    • 更简单:template&lt;typename Fn&gt; std::invoke_result_t&lt;Fn, Widget*&gt;&gt; doIt(Fn&amp;&amp; fn),它也会触发 SFINAE,但更简单且不可绕过。或template&lt;typename Fn&gt; auto doIt(Fn&amp;&amp;fn) -&gt; decltype(fn(_sibling)) {return fn(_sibling);},或template&lt;typename Fn&gt; auto doIt(Fn&amp;&amp;fn){return fn(_sibling);},具体取决于您的编译器版本
    • 这是完美的。如果我在模板中明确指定类型,我希望编译器能够找出类型。我很好奇为什么 template&lt;typename Fn, typename T = std::invoke_result_t&lt;Fn, Widget*&gt;&gt; T doIt(Fn&amp;&amp; fn) 会失败,但是用相同的值替换 T 可以工作 std::invoke_result_t&lt;Fn, Widget*&gt; doIt(...) 工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-25
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    • 1970-01-01
    • 2015-02-03
    • 2019-11-15
    相关资源
    最近更新 更多