来自lambda的C++模板推导

ErW*_*rWu 27 c++ templates

我有一个函数,它需要两个std::functions作为参数.第二个函数的参数与第一个函数的结果具有相同的类型.

我写了一个这样的函数模板:

template<typename ResultType>
void examplFunction(std::function<ResultType()> func, std::function<void(ResultType)> func2) {
  auto x = func();
  func2(x);
}
Run Code Online (Sandbox Code Playgroud)

我可以用它来调用它:

void f() {
  examplFunction<int>([]() { return 1; },   //
                      [](int v) { std::cout << "result is " << v << std::endl; });
}
Run Code Online (Sandbox Code Playgroud)

有没有办法摆脱<int>at examplFunction<int>并让编译器推断出类型ResultType

Rei*_*ica 25

你真的需要std::function在那里吗?std::function在需要类型擦除时很有用.使用模板,您通常可以完全跳过它:

template<class F1, class F2>
void examplFunction(F1 func, F2 func2, decltype(func2(func()))* sfinae = nullptr) {
  auto x = func();
  func2(x);
}
Run Code Online (Sandbox Code Playgroud)

sfinae参数确保只能使用func2可以使用结果调用的函数调用该函数func.

  • @ErWu https://en.wikipedia.org/wiki/SFINAE基本上,如果`func2(func())`格式不正确,它会阻止模板被实例化. (3认同)
  • 请注意,您的SFINAE实际上并不对应于实施.如果`func`返回一个只移动类型(比如,`std :: unique_ptr`)那么SFINAE会允许它,但函数体不会编译.[实施例](https://godbolt.org/z/luZiop). (2认同)

Max*_*hof 12

就在这里.

template<typename ResultType>
void examplFunction_impl(std::function<ResultType()> func, std::function<void(ResultType)> func2) {
    auto x = func();
    func2(x);
}

template<class F1, class F2>
void examplFunction(F1&& f1, F2&& f2)
{
    using ResultType = decltype(f1());
    examplFunction_impl<ResultType>(std::forward<F1>(f1), std::forward<F2>(f2));
}
Run Code Online (Sandbox Code Playgroud)

演示

在这种情况下,您需要f1在没有参数的情况下进行调用,因此您可以在辅助函数中找出返回类型.然后在显式指定返回类型时调用实际函数.

您可以添加一些SFINAE以确保此函数仅在f1确实可以像这样调用时参与重载解析(并且如果f2也可以使用返回值调用f1).

虽然我必须同意@Angew,但在给定的例子中没有必要std::function.在现实世界的情况下,这当然可能有所不同.