【问题标题】:Templates with Function Type Parameter Cause Compiler Error具有函数类型参数的模板导致编译器错误
【发布时间】:2016-03-08 16:38:58
【问题描述】:

我在 C++ 中定义了以下函数:

template<class Type> Type GetMedian(const vector<Type>& items, function<bool(Type, Type)> comp) {
  vector<Type> copied_items(items);
  std::nth_element(copied_items.begin(), copied_items.begin() + copied_items.size()/2, copied_items.end(), comp);
  return copied_items[copied_items.size()/2];
}

但是,当我尝试将其称为 GetMedian(v, greater&lt;uint32_t&gt;()) 时,我的编译器 (clang) 会抱怨:

error: no
      matching function for call to 'GetMedian'
  GetMedian(v, greater<uint32_t>());
  ^~~~~~~~~
note: 
      candidate template ignored: could not match 'function' against 'greater'
template<class Type> Type  GetMedian(const vector<Type>& items, function...

但是,每当我更改为不使用模板时,我都没有看到此错误,因为:

uint32_t GetMedian(const vector<uint32_t>& items, function<bool(uint32_t, uint32_t)> comp) {
  vector<uint32_t> copied_items(items);
  std::nth_element(copied_items.begin(), copied_items.begin() + copied_items.size()/2, copied_items.end(), comp);
  return copied_items[copied_items.size()/2];
}

有什么方法可以让我的功能像我想要的那样灵活吗?

【问题讨论】:

  • 您是否希望模板强制提供的比较函数与向量具有相同的类型,或者如果使用不正确的比较函数会在类型不同时生成编译器错误/警告,是否可以?
  • 我怀疑这是一个不可演绎的上下文问题。您可以通过明确使用模板参数来解决此问题。 GetMedian&lt;uint32_t&gt;(...).

标签: c++ templates generics lambda


【解决方案1】:

Type 类型在这里被推导出两个位置:

template<class Type> 
Type GetMedian(const vector<Type>& items, function<bool(Type, Type)> comp);
                            ^^^^                        ^^^^^^^^^^

当你用GetMedian(v, greater&lt;uint32_t&gt;()) 调用它时,它会将Type 推导出为uint32_t 对应v,但随后它需要推导出function&lt;bool(Type, Type)&gt; 对应greater&lt;uin32_t&gt;。但是后者不是function类型,所以推演失败。 可转换function&lt;bool(uint32_t, uint32_t)&gt;,但在模板推演过程中不会发生转换。

谢天谢地,您实际上并不需要std::function。拥有它实际上更糟糕 - 你无缘无故地给自己带来了类型擦除的开销。只需将比较器设为单独的模板类型即可:

template <class Type, class Comp>
Type GetMedian(const vector<Type>& items, Comp comp);

或者,如果您真的很想要 std::function,您可以通过以下方式将 Type 包装在非推断上下文中:

template <class T> struct non_deduced { using type = T; };
template <class T> using non_deduced_t = typename non_deduced<T>::type;

template <class T>
T median(const std::vector<T>&, std::function<bool(non_deduced_t<T>, non_deduced_t<T>)>)

现在,允许发生从std::greater&lt;uint32_t&gt;std::function&lt;bool(uint32_t, uint32_t)&gt; 的转换,因为只有vector&lt;T&gt; 是推断的上下文,因此编译器将T 推断为uint32_t,然后检查第二个参数是否转换工作。

【讨论】:

  • 你能否解释一下为什么我也可以解决这个问题,方法是在我调用函数时明确指定类型为 GetMedian(v, greater())
猜你喜欢
  • 2020-11-17
  • 1970-01-01
  • 2021-04-23
  • 2013-04-29
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 2013-02-15
  • 2018-05-15
相关资源
最近更新 更多