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
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();
}
- Avoid C-style arrays whenever possible.
- Favor
std::vector
whenever possible. - Genericity over all containers from
std
is good.
尽可能避免使用C风格的数组。
尽可能支持std :: vector。
来自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.5x: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.5x: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
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();
}
- Avoid C-style arrays whenever possible.
- Favor
std::vector
whenever possible. - Genericity over all containers from
std
is good.
尽可能避免使用C风格的数组。
尽可能支持std :: vector。
来自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.5x: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.5x:1.25 y:5.5