基于 lambda 参数重载函数模板

Overloading function template based on lambda arguments

我正在尝试创建一个函数,调用者可以在其中传递具有一组特定已知参数的 lambda(return 类型可以是调用者想要的任何类型) 假设可能的 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 的参数重载函数?

您可以使用 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);
}

请注意,您甚至不需要弄清楚 return 类型 T,您只需使用 auto 即可。

这里是 demo