简体   繁体   English

如何将向量或 valarray 作为参数传递给 C++ 模板 function

[英]How to pass a vector or a valarray as an argument to a C++ template function

I feel this is probably an elementary question, but I can't find a simple answer after quite a bit of searching, so I thought I'd ask.我觉得这可能是一个初级问题,但是经过相当多的搜索后我找不到一个简单的答案,所以我想我会问。

I have a function that is meant to return the nth percentile value in a container, but for legacy reasons the array can be either a vector or valarray, and it can contain doubles or floats.我有一个 function 用于返回容器中的第 n 个百分位值,但由于遗留原因,该数组可以是向量或 valarray,它可以包含双精度数或浮点数。 What is the correct syntax for the function? function 的正确语法是什么? At the moment I have:目前我有:

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]);
}

This compiles OK when passing a valarray, but fails for a vector:这在传递 valarray 时编译正常,但对于向量失败:

'elType GetPercentile(vType &,double)': could not deduce template argument for 'vType &' from 'std::vector<float,std::allocator>' 'elType GetPercentile(vType &,double)': 无法从 'std::vector<float,std::allocator>' 推导出 'vType &' 的模板参数

Is there a way of doing this?有没有办法做到这一点? It seems silly to duplicate the code for the two container types.复制这两种容器类型的代码似乎很愚蠢。 (And if there are any comments on the code itself, that would be fine too.) (如果对代码本身有任何评论,那也很好。)

Many thanks for any advice.非常感谢您的任何建议。 Bill H比尔 H

std::vector has 2 template parameters. std::vector有 2 个模板参数。 The second one is the allocator, which has a default value so you normally don't use it.第二个是分配器,它有一个默认值,所以你通常不使用它。

However, prior to c++17 template template parameters would only match if the number of template arguments where the same.但是,之前的c++17模板参数只会匹配模板参数 arguments 所在的模板数量相同。 In c++17 this was relaxed a bit and it's since allowed to match a template with more template parameters as long as the remaining ones have default arguments.在 c++17 中,这稍微放宽了一点,并且允许匹配具有更多模板参数的模板,只要其余参数具有默认 arguments。

Regardless of this, I would propose a solution that uses the member type in both containers, value_type .不管怎样,我会提出一个在两个容器中使用成员类型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);
}

You are making the template too complicated.您使模板过于复杂。 Just do this.就这样做吧。 No need to static cast.无需 static 投。 Use auto return deduction.使用自动退货扣除。

As an aside, you probably don't want to pass vData by reference because std::nth_element will alter the caller's data in the process of partial sorting.顺便说一句,您可能不想通过引用传递 vData,因为std::nth_element会在部分排序过程中改变调用者的数据。 Also dPercentile is poorly named since you don't scale the fractional value by 100. Consider scaling it or renaming the parameter. 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
};

Thanks very much for the answers and comments - they all contain useful information.非常感谢您的回答和评论——它们都包含有用的信息。 My main problem was not setting VS to use C++17 (duh,).我的主要问题是没有将 VS 设置为使用 C++17 (duh,)。 and not knowing the variadic syntax necessary in C++14 for dealing with the default allocator parameter in vector.并且不知道 C++14 中用于处理向量中的默认分配器参数所需的可变参数语法。 This caused me to thrash around and overcomplicate things, Once I switched to C++17 everything became simpler.这导致我四处奔波并使事情变得过于复杂,一旦我切换到 C++17,一切都变得更简单了。 and worked!并工作! Thanks again (also for the other code-related comments).再次感谢(也感谢其他与代码相关的评论)。 Bill H比尔 H

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM