【问题标题】:Implicit template deduction with lambda expressions [duplicate]使用 lambda 表达式进行隐式模板推导
【发布时间】:2014-05-04 13:41:46
【问题描述】:

我尝试在 XCode 5.1 上使用 c++11 构建以下代码:

template<class T>
float calc2(std::function<float(T)> f) { return -1.0f * f(3.3f) + 666.0f; }

int main(int argc, const char* argv[])
{
    calc2([](float arg) -> float{ return arg * 0.5f; }); //(1) - Will not compile - no matching function...
    calc2<float>([](float arg) -> float{ return arg * 0.5f; }); // (2) - Compiles well
    return 0;
}

有人可以解释为什么 (1) 不能编译吗?编译器不应该从 lambda 定义中推导出 T 吗?

谢谢!

【问题讨论】:

  • std::function 可能用词不当,它是一个函数包装器。 Lambda表达式具有与std::function无关的唯一类型,因此模板类型推导无法成功。
  • 你只能从你直接传入的东西中推断出来,而不是从可以转换为其他东西的东西中推断出来。例如。试试calc2(std::function&lt;float(float)&gt;([](float arg){return arg/2;}))
  • 那么,如果我想强制执行 calc2 接收的函数/lambda 的输入/输出参数,正确的方法是什么?
  • 这就像一个概念。不幸的是,这在 C++11 中不容易做到。例如,您可以尝试template&lt;class F, class = typename std::enable_if&lt; std::is_convertible&lt;typename std::result_of&lt;F(float)&gt;::type, float&gt;{} &gt;::type&gt; float calc2(F f);

标签: templates c++11 lambda


【解决方案1】:

有时没有什么是正确的。 C++ 类型系统会为您完成这些繁琐的工作:

template<class F>
float calc2(F f)
{
  return -1.0f * f(3.3f) + 666.0f;
}

如果你传递任何会使函数无效的东西,它自然会编译失败。

不利的一面是,如果你传递任何不会使函数无效的东西,它会编译,即使它没有意义。如果你想更有选择性,可以使用static_assert

#include <type_traits>

template<class F>
float calc2(F f)
{
  static_assert(std::is_same<float, decltype(f(std::declval<float>()))>::value,
                "The argument must return float when called with float arg!");

  return -1.0f * f(3.3f) + 666.0f;
}

【讨论】:

  • 可以说,这有点贪心。例如。您可能会遇到calc2 的重载解析问题。
  • @dyp 好吧,您在评论中的方法确实存在完全相同的问题。需要添加像float calc2(float (*f)(float)) 这样的重载来修复它。
  • @dyp 只不过是一个std::function,它的贪婪无所不知。
猜你喜欢
  • 2014-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-23
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多