C ++如何传递多个参数?

时间:2022-10-15 15:13:16

Let's assume I have a probability class with a method that computes the average of an array. Because it's possible that this method be passed an array of floats, doubles, ints, etc, I assumed it would be appropriate to make this method a template method.

假设我有一个概率类,其中一个方法可以计算数组的平均值。因为这个方法可能会传递一个float,double,int等数组,所以我认为将这个方法作为模板方法是合适的。

But when passing an array, I have to define a the type of array and length of an array. So my question is: how do I configure the template to accept two inputs? I have referenced the web but have had limited luck in seeing a good example.

但是在传递数组时,我必须定义数组的类型和数组的长度。所以我的问题是:如何配置模板以接受两个输入?我引用了网络,但看到一个好例子的运气有限。

  • Is it valid to define templates to accept parameters that are ints, floats, etc.?
  • 定义模板以接受int,float等参数是否有效?

I've posted my code below

我在下面发布了我的代码

Probability Header

#ifndef COFFEEDEVMATH_PROBABILITY_H
#define COFFEEDEVMATH_PROBABILITY_H

class Probability
{
    public:
         Probability(void);
        template <typename T, int N>
        void ExpectedValueDataSet(const std::array<T, N>& data)
        {
            T test = data[0]; // This is irrelevant, but simply a place holder example.
        }

    protected:
    private:
};

#endif // COFFEEDEVMATH_PROBABILITY_H

Main

#include <iostream>
#include <Probability.h>

int main()
{

    float hoor[] = {3, 3, 1, 1};
    Probability prob;
    prob.ExpectedValueDataSet(hoor, 4);

}

6 个解决方案

#1


3  

Is it valid to define templates to accept parameters that are ints, floats, etc.?

定义模板以接受int,float等参数是否有效?

It's perfectly fine. But to pass an array, you must have an array.

这很好。但要传递数组,您必须拥有一个数组。

std::array<float,4> hoor2 = {3.0f, 3.0f, 1.0f, 1.0f};

In the corresponding template you must use size_t, not int

在相应的模板中,您必须使用size_t,而不是int

template <typename T, size_t N>
void ExpectedValueDataSet(const std::array<T, N>& data) {}

how do I configure the template to accept two inputs?

如何配置模板以接受两个输入?

Just add an additional parameter. To pass a pointer and a length, you create a template that receives a pointer and a length

只需添加一个额外的参数。要传递指针和长度,可以创建一个接收指针和长度的模板

template <typename T>
void ExpectedValueDataSet( T const * data, int N){}

There is also a special syntax for c style arrays that will allow you to pass them without having to specify the length, as that argument will be deduced from the type.

c样式数组还有一种特殊的语法,允许您在不必指定长度的情况下传递它们,因为该参数将从类型中推断出来。

template <typename T, size_t N >
void ExpectedValueDataSet( const T (&data)[N]) { }

Together we have

我们在一起

class Probability
{ 
public:
    template <typename T, size_t N>
    void ExpectedValueDataSet(const std::array<T, N>& data) {}

    template <typename T>
    void ExpectedValueDataSet( T const * data, int N){}

    template <typename T, size_t N>
    void ExpectedValueDataSet(const T (&data)[N]){};
};

See live working exampe here

在这里看看现场工作

#2


3  

The problem is that you've defined your source array as a shitty C array instead of a std::array. If you define your source array as a std::array, you won't have this problem.

问题是你已经将源数组定义为shitty C数组而不是std :: array。如果将源数组定义为std :: array,则不会出现此问题。

Also, there's no need to pass the length in addition, as you have with your example.

此外,除了你的例子之外,没有必要另外传递长度。

#3


2  

Please note that you are trying to pass old plain C array float hoor[] to function with parameter of type std::array<T,N> which is NOT directly compatible with plain C array.

请注意,您正在尝试将旧的普通C数组float hoor []传递给函数,其参数类型为std :: array ,它与普通C数组不直接兼容。 ,n>

Correct syntax to pass plain C array as reference is:

传递普通C数组作为参考的正确语法是:

template <size_t N, typename T>
void ExpectedValueDataSet(const T (&data)[N])
{
    T test = data[0];
}

Usage example:

float hoor_f[] = {3, 3, 1, 1};
ExpectedValueDataSet(hoor_f);

int hoor_i[] = {3, 3, 1, 1};
ExpectedValueDataSet(hoor_i);

#4


1  

Ultimately, I have a feeling that the following is what you should be doing:

最后,我感觉以下是你应该做的:

template<typename C>
typename C::value_type average(C const& c)
{
    return std::accumulate(std::begin(c), std::end(c), C::value_type{}) / c.size();
}
  1. Avoid C-style arrays whenever possible.
  2. 尽可能避免使用C风格的数组。

  3. Favor std::vector whenever possible.
  4. 尽可能支持std :: vector。

  5. Genericity over all containers from std is good.
  6. 来自std的所有容器的通用性都很好。

The above code satisfies all three and works with the following examples:

上面的代码满足所有三个,并使用以下示例:

std::vector<double> vd = { 0., 1., 3., 4.4 };
std::array<float, 4> af = { 3.f, 5.f, 6.f };
std::list<int> li = { 1, 2, 3 };

#5


0  

Actually you can have multiple template arguments but C++ templates offer even more flexibility, you can directly avoid specifying that you are dealing with an array and suppose that you will have access to a size() const method, a value_type typedef and and overloaded operator[].

实际上你可以有多个模板参数,但C ++模板提供了更大的灵活性,你可以直接避免指定你正在处理一个数组,并假设你可以访问size()const方法,value_type typedef和重载运算符[ ]。

This would be enough, so code would become something like:

这就足够了,所以代码会变成:

template <typename T>
void calculate(const T& data)
{
    size_t length = data.size();
    using type = typename T::value_type;
    type value = data[0];
    cout << length << " " << value << endl;
}

This is more generic of your implementation, it would be able to work with all classes which supports the aforementioned characteristics without even bothering about if it's a std::array, or maybe std::vector or what else.

这是你的实现更通用的,它可以使用所有支持上述特性的类,甚至不用担心它是std :: array,还是std :: vector或者其他什么。

#6


0  

Pass a container to a template function like this.

将容器传递给这样的模板函数。

#include <iostream>

template<typename T>
double average(T t) {
    auto tmp = 0.0;
    for (auto &i : t) {
        tmp += i;
    }
    return tmp/t.size();
}

using namespace std;

int main(int argc, char const *argv[])
{
    auto a = {1.0, 1.1, 1.2, 1.3};
    auto b = {2, 3, 4, 5};
    auto x = average(a);
    auto y = average(b);
    cout << "x: " << x << endl;
    cout << "y: " << y << endl;
    return 0;
}

x: 1.15
y: 3.5

x:1.15 y:3.5

And using lambda. The auto keyword in lambdas requires C++14 and later.

并使用lambda。 lambda中的auto关键字需要C ++ 14及更高版本。

auto average = [](auto v){
    auto tmp = 0.0;
    for (auto& i : v) {
        tmp += i;
    }
    return tmp/v.size();
};
auto a = {1.1, 1.2, 1.3, 1.4};
auto b = {2, 3, 4, 5, 6, 7, 8, 9};
auto x = average(a);
auto y = average(b);
cout << "x: " << x << endl;
cout << "y: " << y << endl;

x: 1.25
y: 5.5

x:1.25 y:5.5

#1


3  

Is it valid to define templates to accept parameters that are ints, floats, etc.?

定义模板以接受int,float等参数是否有效?

It's perfectly fine. But to pass an array, you must have an array.

这很好。但要传递数组,您必须拥有一个数组。

std::array<float,4> hoor2 = {3.0f, 3.0f, 1.0f, 1.0f};

In the corresponding template you must use size_t, not int

在相应的模板中,您必须使用size_t,而不是int

template <typename T, size_t N>
void ExpectedValueDataSet(const std::array<T, N>& data) {}

how do I configure the template to accept two inputs?

如何配置模板以接受两个输入?

Just add an additional parameter. To pass a pointer and a length, you create a template that receives a pointer and a length

只需添加一个额外的参数。要传递指针和长度,可以创建一个接收指针和长度的模板

template <typename T>
void ExpectedValueDataSet( T const * data, int N){}

There is also a special syntax for c style arrays that will allow you to pass them without having to specify the length, as that argument will be deduced from the type.

c样式数组还有一种特殊的语法,允许您在不必指定长度的情况下传递它们,因为该参数将从类型中推断出来。

template <typename T, size_t N >
void ExpectedValueDataSet( const T (&data)[N]) { }

Together we have

我们在一起

class Probability
{ 
public:
    template <typename T, size_t N>
    void ExpectedValueDataSet(const std::array<T, N>& data) {}

    template <typename T>
    void ExpectedValueDataSet( T const * data, int N){}

    template <typename T, size_t N>
    void ExpectedValueDataSet(const T (&data)[N]){};
};

See live working exampe here

在这里看看现场工作

#2


3  

The problem is that you've defined your source array as a shitty C array instead of a std::array. If you define your source array as a std::array, you won't have this problem.

问题是你已经将源数组定义为shitty C数组而不是std :: array。如果将源数组定义为std :: array,则不会出现此问题。

Also, there's no need to pass the length in addition, as you have with your example.

此外,除了你的例子之外,没有必要另外传递长度。

#3


2  

Please note that you are trying to pass old plain C array float hoor[] to function with parameter of type std::array<T,N> which is NOT directly compatible with plain C array.

请注意,您正在尝试将旧的普通C数组float hoor []传递给函数,其参数类型为std :: array ,它与普通C数组不直接兼容。 ,n>

Correct syntax to pass plain C array as reference is:

传递普通C数组作为参考的正确语法是:

template <size_t N, typename T>
void ExpectedValueDataSet(const T (&data)[N])
{
    T test = data[0];
}

Usage example:

float hoor_f[] = {3, 3, 1, 1};
ExpectedValueDataSet(hoor_f);

int hoor_i[] = {3, 3, 1, 1};
ExpectedValueDataSet(hoor_i);

#4


1  

Ultimately, I have a feeling that the following is what you should be doing:

最后,我感觉以下是你应该做的:

template<typename C>
typename C::value_type average(C const& c)
{
    return std::accumulate(std::begin(c), std::end(c), C::value_type{}) / c.size();
}
  1. Avoid C-style arrays whenever possible.
  2. 尽可能避免使用C风格的数组。

  3. Favor std::vector whenever possible.
  4. 尽可能支持std :: vector。

  5. Genericity over all containers from std is good.
  6. 来自std的所有容器的通用性都很好。

The above code satisfies all three and works with the following examples:

上面的代码满足所有三个,并使用以下示例:

std::vector<double> vd = { 0., 1., 3., 4.4 };
std::array<float, 4> af = { 3.f, 5.f, 6.f };
std::list<int> li = { 1, 2, 3 };

#5


0  

Actually you can have multiple template arguments but C++ templates offer even more flexibility, you can directly avoid specifying that you are dealing with an array and suppose that you will have access to a size() const method, a value_type typedef and and overloaded operator[].

实际上你可以有多个模板参数,但C ++模板提供了更大的灵活性,你可以直接避免指定你正在处理一个数组,并假设你可以访问size()const方法,value_type typedef和重载运算符[ ]。

This would be enough, so code would become something like:

这就足够了,所以代码会变成:

template <typename T>
void calculate(const T& data)
{
    size_t length = data.size();
    using type = typename T::value_type;
    type value = data[0];
    cout << length << " " << value << endl;
}

This is more generic of your implementation, it would be able to work with all classes which supports the aforementioned characteristics without even bothering about if it's a std::array, or maybe std::vector or what else.

这是你的实现更通用的,它可以使用所有支持上述特性的类,甚至不用担心它是std :: array,还是std :: vector或者其他什么。

#6


0  

Pass a container to a template function like this.

将容器传递给这样的模板函数。

#include <iostream>

template<typename T>
double average(T t) {
    auto tmp = 0.0;
    for (auto &i : t) {
        tmp += i;
    }
    return tmp/t.size();
}

using namespace std;

int main(int argc, char const *argv[])
{
    auto a = {1.0, 1.1, 1.2, 1.3};
    auto b = {2, 3, 4, 5};
    auto x = average(a);
    auto y = average(b);
    cout << "x: " << x << endl;
    cout << "y: " << y << endl;
    return 0;
}

x: 1.15
y: 3.5

x:1.15 y:3.5

And using lambda. The auto keyword in lambdas requires C++14 and later.

并使用lambda。 lambda中的auto关键字需要C ++ 14及更高版本。

auto average = [](auto v){
    auto tmp = 0.0;
    for (auto& i : v) {
        tmp += i;
    }
    return tmp/v.size();
};
auto a = {1.1, 1.2, 1.3, 1.4};
auto b = {2, 3, 4, 5, 6, 7, 8, 9};
auto x = average(a);
auto y = average(b);
cout << "x: " << x << endl;
cout << "y: " << y << endl;

x: 1.25
y: 5.5

x:1.25 y:5.5