【问题标题】:Template deduction for variadic template lambda arguments可变参数模板 lambda 参数的模板推导
【发布时间】:2017-02-13 02:51:22
【问题描述】:

给定以下可变参数模板:

template<typename... Params>
void fun(void(*f)(Params...), Params... params) {
  f(params...);
}

int main() {
  fun(+[](int a, int b) {}, 2, 3);
}

现在,当使用 lambda 调用 fun 时,我需要明确指定所有 lambda 参数的类型。这似乎是多余的,因为int, int 可以从2, 3 推导出来。有没有办法让它更简洁和自动化?

我希望下面的工作,但它没有:

template<typename... Params>
void fun(void(*f)(Params...), Params... params) {
  f(params...);
}

int main() {
  fun(+[](auto a, auto b) {}, 2, 3);
}

我正在使用g++ 5.4.0-std=c++14 进行编译。

【问题讨论】:

  • 您在输入int 而不是auto 时遇到问题?
  • @Brian 是的,因为它需要我推断它是int。可以再长一点,让它更具戏剧性。

标签: c++ templates lambda generic-lambda


【解决方案1】:

通过T而不是指针获取函数:

template<typename T, typename... Params>
void fun(T f, Params... params) {
  f(params...);
}

int main() {
  fun([](auto a, auto b) {}, 2, 3);
}

这样,如果在+ 运算符内,编译器可以选择在调用站点调用哪个重载的权利。正如评论中所说,无论如何都没有为通用 lambda 定义 + 运算符。


或者,您可以禁止编译器尝试使用标识别名从函数指针中推断出Params,但我真的不推荐。无论如何,给你:

template<typename T>
struct identity { using type = T; };

template<typename T>
using identity_t = typename identity<T>::type;

template<typename... Params>
void fun(void(*f)(identity_t<Params>...), Params... params) {
  f(params...);
}

int main() {
  //  v----- no unary +. That operator is not defined for generic lambdas.
  fun([](auto a, auto b) {}, 2, 3);
}

【讨论】:

  • 请注意,非泛型 lambda 也没有 + 运算符。使用了内置的+ 操作符,但是 lambda 被强制转换为一个指针,使用它的转换操作符到函数指针。
猜你喜欢
  • 2013-09-14
  • 1970-01-01
  • 2020-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 1970-01-01
  • 2016-12-01
相关资源
最近更新 更多