【问题标题】:How to pass a vector or a valarray as an argument to a C++ template function如何将向量或 valarray 作为参数传递给 C++ 模板函数
【发布时间】:2022-01-17 06:29:54
【问题描述】:

我觉得这可能是一个初级问题,但经过相当多的搜索后我找不到简单的答案,所以我想我会问。

我有一个函数旨在返回容器中的第 n 个百分位值,但由于遗留原因,该数组可以是向量或 valarray,它可以包含双精度数或浮点数。该函数的正确语法是什么? 目前我有:

template <template <class> class vType, class elType>
elType GetPercentile(vType<elType>& vData, double dPercentile)
{
    int iOffset = int(dPercentile * vData.size());
    std::nth_element(begin(vData), begin(vData) + iOffset, end(vData));
    return static_cast<elType>(vData[iOffset]);
}

这在传递一个 valarray 时编译正常,但对于一个向量失败:

'elType GetPercentile(vType &,double)': 无法从 'std::vector' 推导出 'vType &' 的模板参数

有没有办法做到这一点?复制这两种容器类型的代码似乎很愚蠢。 (如果代码本身有任何 cmets,那也可以。)

非常感谢您的任何建议。 比尔H

【问题讨论】:

  • 对我来说,此代码适用于std::vector&gt;。您使用的是哪个编译器?哪个c++版本?我使用 gcc,C++17。
  • vector有两个模板参数,其中一个是默认的。您可能需要选择一个相当新的标准来支持它来匹配template &lt;class&gt; class vType 而不仅仅是template &lt;class, class&gt; class vType
  • template &lt;class, class...&gt; class vType 应该在 c++11 及更高版本中工作。如答案中所示,这个特定问题允许更简单的解决方案,但是当您确实需要模板模板参数时,这就是您在 c++17 之前的方式。

标签: c++ templates vector valarray


【解决方案1】:

您使模板过于复杂。就这样做吧。无需静态转换。使用自动退货扣除。

顺便说一句,您可能不想通过引用传递 vData,因为std::nth_element 会在部分排序过程中改变调用者的数据。 dPercentile 的命名也很糟糕,因为您没有将小数值缩放 100。考虑缩放它或重命名参数。

#include <vector>
#include <valarray>
#include <algorithm>

template<class vType>
auto GetPercentile(vType vData, double dPercentile)
{
    int iOffset = int(dPercentile * vData.size());
    std::nth_element(begin(vData), begin(vData) + iOffset, end(vData));
    return vData[iOffset];
}

int main()
{
    std::vector<float> v{ 1,2,3,4 };
    std::valarray<float> va{ 1., 2., 3., 4. };
    auto nth_v = GetPercentile(v, .5);   //returns 3.f
    auto nth_va = GetPercentile(va, .5); //returns 3.f
};

【讨论】:

  • 感谢您的回复。事实证明,我的主要问题是没有将 VS 设置为使用 C++17(呃!),并且不知道 C++14 中处理向量中的默认分配器参数所需的可变参数语法。这使我四处奔波,使事情变得过于复杂。一旦我切换到 C++17,一切都变得更简单了,并且工作正常!再次感谢(也感谢其他与代码相关的 cmets)。
【解决方案2】:

std::vector 有 2 个模板参数。第二个是分配器,它有一个默认值,所以你通常不会使用它。

但是,c++17 之前的模板模板参数只有在模板参数的数量相同的情况下才会匹配。在 c++17 中,这稍微放宽了一点,并且允许匹配具有更多模板参数的模板,只要剩余的模板参数具有默认参数。

不管怎样,我会提出一个在两个容器中都使用成员类型的解决方案,value_type

#include <vector>
#include <algorithm>
#include <valarray>

template <class T>
auto GetPercentile(T& vData, double dPercentile)
{
    using elType = typename T::value_type;
    int iOffset = int(dPercentile * vData.size());
    std::nth_element(begin(vData), begin(vData) + iOffset, end(vData));
    return static_cast<elType>(vData[iOffset]);
}

int main() {
    auto v = std::vector<int>{1,2,3,4,5};
    GetPercentile(v, 2);

    auto a = std::valarray<int>(5, 5);
    GetPercentile(a, 2);
}

【讨论】:

  • 程序产生 UB。 dPercentile 应
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
相关资源
最近更新 更多