如何显式转换参数以匹配期望的函数参数?

时间:2018-11-10 10:09:45

标签: c++ c++11 c++14 c++17 typetraits

我正在尝试编写一个通用函数来计算特定范围内的平均值。

template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract) {
  Ret sum = zero;
  int numElements = 0;
  for (const auto& elem : range) {
    sum += extract(elem);
    ++numElements;
  }
  if (numElements > 0)
    sum /= numElements;
  return sum;
}

我遇到的问题是使用/=运算符,但是为了更好地阐明此函数的参数,让我澄清它们:

  • Range range是通过begin()end()成员函数定义范围的任何对象。我可能需要添加const&以避免不必要的复制。
  • Ret zero定义了计算平均值时所用加法的中性元素。它可能只是一个标量,但是例如也可以用于向量或矩阵。
  • Func extract是一个函数(通常以lambda函数形式给出),可将范围的元素转换为我平均的Ret值。在实践中,我将它用作迭代的大对象中特定字段的吸气剂。

    如果C ++在用这种方式推断类型时没有问题,我可能将其定义为std::function<Ret(decltype(*range.begin()))>或类似的名称。

我假设Ret提供了上述功能可以使用的 some /=运算符,但我不想要求它采用int

例如,在我的用例中,Retfloat-s一起使用,这给了我一个烦人的警告:

warning: 'argument': conversion from 'int' to 'float', possible loss of data

那么,我可以采取哪些措施使上述功能更干净并与任何合适的operator/=配合使用?


例如,我尝试推导运算符的正确参数的类型并将其显式转换为它:

template <typename Range, typename Ret, typename Func>
Ret average(Range range, Ret zero, Func extract) {
  Ret sum = zero;
  int numElements = 0;
  for (const auto& elem : range) {
    sum += extract(elem);
    ++numElements;
  }
  using F = std::remove_pointer<decltype(&Ret::operator/=)>;

  if (numElements > 0)
    sum /= static_cast<typename boost::function_traits<F>::arg1_type>(numElements);
  return sum;
}

但是我遇到很多编译错误,表明我不知道自己在做什么。开头为:

error: 'boost::detail::function_traits_helper<std::remove_pointer<SpecificTypeUsedAsRet &(__cdecl SpecificTypeUsedAsRet::* )(float)> *>': base class undefined

这可能是因为boost::function_traits不能用于成员函数,而只能用于常规函数吗?

我还担心在以下情况下该解决方案可能无法正常工作

  • operator/=不是作为成员函数给出的,而是作为具有两个参数的常规函数​​给出的。
  • operator/=的右操作数过载。 int可能只匹配其中一个重载-因此没有歧义,但是decltype不知道要承担哪个重载。
  • 我不希望使用boost,而是坚持使用最新的C ++标准提供的功能

1 个答案:

答案 0 :(得分:0)

您可以简单地声明Ret numElements = 0;而不是使其成为int。如果它有/=运算符,则可能有一个++运算符;或者您也可以使用num_elements += 1