如何使用lambda作为第一个参数覆盖可变参数模板

How to override a variadic template with lambda as the first parameter?

本文关键字:参数 覆盖 变参 第一个 何使用 lambda      更新时间:2023-10-16

为什么下面的函数重写(lambda作为第一个参数)不工作?

template<typename ...Args>
void call(Args&& ...args) {
    std::cout << "call 1";
}
template<typename ...Args>
void call(CustomObject object, Args&& ...args) {
    std::cout << "call 2";
}
// see this function
template<typename ...Args>
void call(std::function<void ()>, Args&& ...args) {
    std::cout << "call 3";
}
  • call()输出 ' call 1 '
  • call(CustomObject())输出'call 2'
  • call([](){})输出"电话1"//

为什么call([](){})不输出'call 3'?

我该如何声明函数让call([](){})输出'调用3'?

编辑: @KennyTM给出了上述问题的答案。

template<typename F, typename ...Args>
auto call(F&& f, Args&& ...args)
    -> typename std::enable_if<std::is_same<decltype(f()), void>::value>::type
{
    std::cout << "call 3n";
}

但是…如果有参数呢?这样的:

class CustomObject {};
template<typename ...Args>
void call(std::function<void (CustomObject *)>, Args&& ...args) {
    std::cout << "call 4";
}

如何让call([](CustomObject *){})输出'调用4'?

编辑: @ildjarn给出了答案:

template<typename F, typename ...Args>
auto call(F&& f, Args&& ...)
    -> typename std::enable_if<std::is_same<decltype(f( std::declval<CustomObject*>() )), void>::value>::type
{
    std::cout << "call 4n";
}

lambda的类型是具有operator()的匿名类型。它不是std::function<>

您可以检查第一个参数是否是调用3的函子,而不是专门化类型(demo: http://ideone.com/IQ4N6L):

)。
#include <iostream>
#include <type_traits>
template<typename F, typename ...Args>
auto call(F&& f, Args&& ...args)
    -> typename std::enable_if<std::is_same<decltype(f()), void>::value>::type
{
    std::cout << "call 3n";
}

template<typename ...Args>
void call(Args&& ...args) {
    std::cout << "call 1n";
}

int main() {
    call(1);
    call([](){});
}