gpt4 book ai didi

c++ - 带有 std::function 的模板不直接匹配 lambda

转载 作者:行者123 更新时间:2023-11-30 05:11:49 24 4
gpt4 key购买 nike

如何最好地定义模板函数 applyFunc 以匹配 lambda 的签名?

我不想定义一个通用的模板参数来捕获整个函数类型,因为我想使用传入函数参数的类型E

#include <functional>
template<class E>
int applyFunc(std::function<int(E)> f) {
return f(E{});
}

int main()
{
auto asLambda = [](int d) -> int { return d+d; };
std::function<int(int)> asFunc = asLambda;

applyFunc(asLambda); //this doesn't :(
applyFunc(asFunc); //this works
}

编译失败:

15:23: error: no matching function for call to 'applyFunc(main()::<lambda(int)>&)'
15:23: note: candidate is:
6:5: note: template<class E> int applyFunc(std::function<int(E)>)
6:5: note: template argument deduction/substitution failed:
15:23: note: 'main()::<lambda(int)>' is not derived from 'std::function<int(E)>'

最佳答案

How can I best define the template function applyFunc to match lambda's the signature ?

只要您接受仅使用非捕获 lambda(就像您在示例代码中所做的那样),您就可以利用它们衰减为函数指针这一事实。
作为一个最小的工作示例:

template<class E>
int applyFunc(int(*f)(E)) {
return f(E{});
}

int main() {
auto asLambda = [](int d) -> int { return d+d; };
applyFunc(+asLambda);
}

如果您想改为使用捕获 lambda 表达式,则可以在接受以下条件的情况下以某种方式提取类型 E:

  • 您必须使用泛型 F 而不是 std::function
  • 你不能使用通用的 lambdas

然后,您可以直接查看您的 lambda 的 operator()
它遵循一个最小的工作示例:

template<typename F>
struct GetFrom {
template<typename R, typename E>
static E typeE(R(F::*)(E) const);

// required for mutable lambdas
template<typename R, typename E>
static E typeE(R(F::*)(E));
};

template<class F>
int applyFunc(F f) {
using E = decltype(GetFrom<F>::typeE(&F::operator()));
return f(E{});
}

int main() {
int i = 0;
applyFunc([i](int d) mutable -> int { return d+d; });
applyFunc([i](int d) -> int { return d+d; });
}

如果需要,您可以轻松地将其扩展到多个参数。使用 std::tuple 作为返回类型并从中获取第 i 个类型。

最后,如果您想使用捕获 lambda 并将它们分配给 std::function,无论出于何种原因,请注意 E 无法自动推导,因此您必须明确指定它(正如@cpplearner 对问题的评论中所建议的):

applyFunc<int>([](int d) { return d+d; })

编辑

GetFrom 也可以按照注释中的要求直接在 SFINAE 表达式中使用。
作为一个最小的工作示例:

#include<type_traits>

template<typename F>
struct GetFrom {
template<typename R, typename E>
static E typeE(R(F::*)(E) const);

// required for mutable lambdas
template<typename R, typename E>
static E typeE(R(F::*)(E));
};

template<class F, typename E = decltype(GetFrom<F>::typeE(&F::operator()))>
std::enable_if_t<std::is_same<E, int>::value, E>
applyFunc(F f) {
return f(E{});
}

template<class F, typename E = decltype(GetFrom<F>::typeE(&F::operator()))>
std::enable_if_t<std::is_same<E, double>::value, E>
applyFunc(F f) {
return f(E{});
}

int main() {
int i = 0;
applyFunc([i](int d) mutable -> int { return d+d; });
applyFunc([i](double d) -> int { return d+d; });
// this won't compile, as expected
// applyFunc([i](char d) -> int { return d+d; });
}

关于c++ - 带有 std::function 的模板不直接匹配 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44871396/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com