【问题标题】:Deduce template argument from std::function call signature从 std::function 调用签名推断模板参数
【发布时间】:2012-06-21 15:14:26
【问题描述】:

考虑这个模板函数:

template<typename ReturnT>
ReturnT foo(const std::function<ReturnT ()>& fun)
{
    return fun();
}

为什么编译器不能从传递的调用签名中推断出ReturnT

bool bar() { /* ... */ }

foo<bool>(bar); // works
foo(bar); // error: no matching function call

【问题讨论】:

标签: c++ templates std-function template-argument-deduction


【解决方案1】:

bool (*)() 类型的函数指针可以转换为std::function&lt;bool()&gt; 但不是同一类型,因此需要进行转换。在编译器可以检查该转换是否可能之前,它需要将ReturnT 推断为bool,但要做到这一点,它需要已经知道std::function&lt;bool()&gt; 是一种可能的转换,直到它推断出@987654326 之前是不可能的@ ... 看到问题了吗?

另外,考虑bool(*)() 也可以转换为std::function&lt;void()&gt;std::function&lt;int()&gt; ...应该推导出来?

考虑这种简化:

template<typename T>
  struct function
  {
    template<typename U>
      function(U) { }
  };

template<typename T>
  void foo(function<T>)
  { }

int main()
{
    foo(1);
}

当它们都可以从int 构造时,编译器如何知道您是要创建function&lt;int&gt;function&lt;char&gt; 还是function&lt;void&gt;

【讨论】:

    【解决方案2】:
    std::function<bool()> bar;
    
    foo(bar); // works just fine
    

    C++ 无法从您的函数bar 推断出返回类型,因为它必须知道类型才能找到所有使用您的函数指针的构造函数。

    例如,谁能说std::function&lt;std::string()&gt; 没有构造函数采用bool (*)()

    【讨论】:

      【解决方案3】:

      函数bar的类型为bool (*)()左右,即:一个普通的pre-C++11函数类型。我对 C++11 没有那么自信,但我猜编译器看不到 bool (*)()const std::function&lt;ReturnT()&gt;&amp; 之间的联系,即使第一个可以隐式转换为 ReturnT = bool 的第二个。

      【讨论】:

      • 实际上,无论转换如何进行,std::function 的定义是:template&lt;class R, class... Args&gt; class function&lt;R(Args...)&gt; 其中R 已知为bool ...因此ReturnT 应该可以推导出为@ 987654330@,对吧?
      • @Karl,但 std::function 有一个采用 any 类型的构造函数,因此 bool(*)() 也可以转换为 std::function&lt;void()&gt; 或其他类型 - 没有单一的、唯一的转换序列,这意味着只能推断出单一的std::function 特化
      • @JonathanWakely 好的,我想我现在明白了。感谢您的帮助:-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多