如何将向量或 valarray 作为参数传递给 C++ 模板函数
How to pass a vector or a valarray as an argument to a C++ template function
我觉得这可能是一个初级问题,但经过大量搜索后找不到简单的答案,所以我想问一下。
我有一个函数旨在 return 容器中的第 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)': could not deduce template argument for 'vType &' from 'std::vector<float,std::allocator>'
有办法吗?为两种容器类型复制代码似乎很愚蠢。 (如果对代码本身有任何评论,那也很好。)
非常感谢您的任何建议。
比尔·H
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);
}
您使模板过于复杂。就这样做吧。无需静态投射。使用自动 return 扣除。
顺便说一句,您可能不想通过引用传递 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
};
我觉得这可能是一个初级问题,但经过大量搜索后找不到简单的答案,所以我想问一下。
我有一个函数旨在 return 容器中的第 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)': could not deduce template argument for 'vType &' from 'std::vector<float,std::allocator>'
有办法吗?为两种容器类型复制代码似乎很愚蠢。 (如果对代码本身有任何评论,那也很好。)
非常感谢您的任何建议。 比尔·H
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);
}
您使模板过于复杂。就这样做吧。无需静态投射。使用自动 return 扣除。
顺便说一句,您可能不想通过引用传递 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
};