代码之家  ›  专栏  ›  技术社区  ›  CygnusX1 Stack Overflow is garbage

如何显式强制转换参数以匹配预期的函数参数?

  •  0
  • CygnusX1 Stack Overflow is garbage  · 技术社区  · 7 年前

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

    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 我的平均值。在实践中,我使用它作为我迭代的大对象中特定字段的getter。

      我可以把它定义为 std::function<Ret(decltype(*range.begin()))> 或者类似的东西,如果C++没有问题,这样就可以推断出类型。

    我想 Ret 提供 一些 /= 运算符,上面的函数可以使用,但我不想要求它 int 明确地

    例如,在我的用例中, Ret 合作 float -这给了我一个恼人的警告:

    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 不适用于成员函数,只适用于常规函数?

    我还担心,在以下情况下,这种解决方案可能无法奏效:

    • 这个 接线员/= 不是作为成员函数给出的,而是作为带有两个参数的正则函数给出的。
    • 这个 接线员/= 相对于其右操作数重载。一 智力 可能只匹配其中一个重载-因此没有歧义,但是 decltype 不知道该承受哪种超负荷。
    • 我宁愿不使用 boost 但要坚持由最新的C++标准提供的权力
    1 回复  |  直到 7 年前
        1
  •  0
  •   Aganju    7 年前

    你可以简单地申报 Ret numElements = 0; 而不是让它成为 int .如果有 /= 接线员,它可能有一个 ++ 操作人员或者你可以用 num_elements += 1 相反