我正在创建一个包含数值数据向量的模板类(可以是int,float,double等)。它有一个操作,在数据上调用std::abs()
。类似下面的代码。
#include <iostream>
#include <complex>
#include <vector>
template<typename T> class MyData
{
public:
std::vector<T> data;
MyData<T> my_abs() const;
};
template<typename T>
MyData<T> MyData<T>::my_abs() const
{
MyData<T> output;
output.data.reserve(data.size());
typename std::vector<T>::const_iterator it;
for (it = data.begin(); it != data.end(); it++)
{
output.data.push_back(std::abs(*it));
}
return output;
}
int main()
{
MyData<double> A;
A.data = std::vector<double>(10, -1.0);
MyData<double> test = A.my_abs();
for (auto el : test.data)
{
std::cout << el << std::endl;
}
return 0;
}
这适用于int,float,double等类型。我还希望能够将此类用于std::complex<double>
。
环顾四周,我发现我可以使用模板模板参数:
template<template<typename> class T, typename U> class MyData
{
public:
std::vector<T<U>> data;
MyData<U> my_abs() const;
};
template<template<typename> class T, typename U>
MyData<U> MyData<T<U>>::my_abs() const
{
MyData<U> output;
output.data.reserve(data.size());
typename std::vector<T<U>>::const_iterator it;
for (it = data.begin(); it != data.end(); it++)
{
output.data.push_back(std::abs(*it));
}
return output;
}
之前的代码不起作用,因为我的模板类需要两个参数,
error: wrong number of template arguments (1, should be 2)
MyData<U> abs() const;
^
理想情况下,我想要像以前的代码一样。其中my_abs()
函数返回传递给我的模板的模板参数的类型。例如,如果我使用std::complex<double>
,那么我的主要功能可能类似于:
int main()
{
MyData<std::complex<double>> A;
A.data = std::vector<std::complex<double>>(10, std::complex<double>(-1.0, -1.0));
MyData<double> test = A.my_abs();
for (auto el : test.data)
{
std::cout << el << std::endl;
}
return 0;
}
我不确定如何实现这一目标(或者甚至可以使用相同的模板类)。
答案 0 :(得分:3)
您可以在声明中使用std::abs(T)
的返回类型。
示例:
#include <iostream>
#include <complex>
#include <vector>
#include <cmath>
#include <utility>
template<typename T> class MyData
{
public:
std::vector<T> data;
using abs_type = decltype(std::abs(std::declval<T>()));
auto my_abs() -> MyData<abs_type> const;
};
template<typename T>
auto MyData<T>::my_abs() -> MyData<abs_type> const
{
MyData<abs_type> output;
output.data.reserve(data.size());
typename std::vector<T>::const_iterator it;
for (it = data.begin(); it != data.end(); it++)
{
output.data.push_back(std::abs(*it));
}
return output;
}
int main()
{
MyData<std::complex<double>> A;
A.data = std::vector<std::complex<double>>(10, std::complex<double>(-1.0, -1.0));
auto test = A.my_abs();
for (auto el : test.data)
{
std::cout << el << std::endl;
}
return 0;
}
答案 1 :(得分:0)
你必须以这种方式写你的专业
template<template<typename> class T, typename U>
class MyData<T<U>> // <----- note the <T<U>>
{
public:
std::vector<T<U>> data;
MyData<U> my_abs() const;
};
答案 2 :(得分:0)
你不需要一个类,模板函数就足够了。您可以为模板功能提供abs
功能,例如
template<typename T, typename F> std::vector<T> my_abs(const std::vector<T> &in, F abs) {
std::vector<T> out;
for (auto &i: in) {
out.push_back(abs(i));
}
return out;
}
将其称为
std::vector<int> res = my_abs(in, special_abs);
如果输入和输出的类型不同,则可以在T
和U
上进行参数化。
正如@ Jarod42已经指出的那样,这对于像std::abs
这样的重载函数不起作用。
你可以通过给lambda作为第二个参数来解决这个问题,例如
std::vector<int> res = my_abs(in, [](const auto& e) { return std::abs(e);});
另一种解决方法是通过强制转换为正确的类型
来明确选择适当的abs
std::vector<int> res = my_abs(in, static_cast<double(*)(double)>(std::abs));