【问题标题】:How to infer a function type parameter in a template function with a lambda passed as argument?如何使用作为参数传递的 lambda 在模板函数中推断函数类型参数?
【发布时间】:2016-12-28 11:45:56
【问题描述】:

考虑以下几点:

#include <utility>
#include <string>

template<typename>
class C;

template<typename R, typename T>
class C<R(&)(T)> {
public:
    template<typename F>
    C(F&& fun) {}
};

template<typename T>
C<T> makeC(T&& fun) {
    return C<T>(std::forward<T>(fun));
}

int foo(int a){return a;}

int main() {
    auto p1 = makeC(foo); // OK
    auto p2 = C<int(&)(int)>([](int a){return a;});   // OK
    // auto p3 = makeC([](int a){return a;}); // FAIL
}

Live example

p3 的声明失败,因为编译器无法从作为参数传递的 lambda 推断类型 int(&amp;)(int)p1 可以,因为可以从函数foo 轻松推断出类型,而p2 可以,因为类型是显式声明的。

它失败了:

error: invalid use of incomplete type 'class C&lt;main()::&lt;lambda(int)&gt; &gt;'

有没有办法让编译器在给定 lambda 的情况下正确推断函数类型?

P.S.:如果适用,C++17 的答案也可以。

【问题讨论】:

标签: c++ templates lambda c++14 type-inference


【解决方案1】:

实际的问题是 lambda 函数有它自己的类型,不能简化为 R(&amp;)(T)。因此,C&lt;T&gt; 是编译器正确列出的不完整类型。


只要您使用非捕获 lambda,您就可以依靠它们衰减为函数指针的事实来执行此操作:

auto p3 = makeC(*(+[](int a){return a;}));

或者这个:

template<typename T>
auto makeC(T&& fun) -> C<decltype(*(+std::forward<T>(fun)))> {
    return C<decltype(*(+std::forward<T>(fun)))>(std::forward<T>(fun));
}

另一种适用于捕获 lambda 的可能解决方案是:

#include <utility>
#include <string>

template<typename T>
class C: T {
    template<typename F>
    C(F&& fun): T{std::forward<F>(fun)} {}
};

template<typename R, typename T>
class C<R(&)(T)> {
public:
    template<typename F>
    C(F&& fun) {}
};

template<typename T>
C<T> makeC(T&& fun) {
    return C<T>(std::forward<T>(fun));
}

int foo(int a){return a;}

int main() {
    auto p1 = makeC(foo);
    auto p2 = C<int(&)(int)>([](int a){return a;});
    auto p3 = makeC([](int a){return a;});
}

这样,在处理 lambda 时,C 实际上是从它继承并私下包含它的operator()

【讨论】:

  • 很好的答案,谢谢!您的最终解决方案效果很好,但不幸的是,我需要能够在我的模板实例中区分 lambda 的参数类型。我想我会坚持只支持非捕获 lambda,因为这在我的场景中并不是一个可怕的限制。
猜你喜欢
  • 2017-06-14
  • 2019-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多