如何分解以下代码,以便可以遍历T = double
和T = float
?我已经阅读了可变参数模板,但是我
不了解如何在这种情况下应用它:
int main(int argc, char* argv[])
{
ofstream writeDat;
vector<int> nValues = {26,51,101,201};
for(int i = 0; i< 4; i++){
int N = nValues[i];
typedef float T ;
Matrix<T> a(N,N);
Matrix<T> b(N,3);
Matrix<T> x = Problem2<T>(N);
string sFloat = "2/" + to_string(N) + "Float"+".dat";
writeDat.open(sFloat);
for(int i =1; i<N ; i++)
writeDat << i << " " << x(i,1)<<endl;
writeDat << N <<" "<< x(N,1)<< endl;
writeDat.close();
}
for(int i = 0; i< 4; i++){
int N = nValues[i];
typedef double T ;
Matrix<T> a(N,N);
Matrix<T> b(N,3);
Matrix<T> x = Problem2<T>(N);
string s = "2/" + to_string(N) + "Double"+".dat";
writeDat.open(s);
for(int i =1; i<N ; i++)
writeDat << i << " " << x(i,1)<<endl;
writeDat << N <<" "<< x(N,1)<< endl;
writeDat.close();
}
return 0;
}
答案 0 :(得分:2)
使用可变参数扩展来调用包含重复逻辑的模板函数(或可变参数lambda):
#include<fstream>
#include<vector>
// the concept of a type wrapper
template<class T> struct type_wrapper;
// a model of type_wrapper for floats
template<>
struct type_wrapper<float> {
using type = float;
constexpr const char* name() const { return "Float"; }
};
// a model of type_wrapper for doubles
template<>
struct type_wrapper<double> {
using type = double;
constexpr const char* name() const { return "Double"; }
};
// call a template function once for each type wrapper in Ts...
template<class...Ts, class F>
auto for_each_type(F&& f)
{
(f(type_wrapper<Ts>()),...);
}
template<class T>
struct Matrix
{
Matrix(int, int);
T& operator()(int, int);
};
template<class T> Matrix<T> Problem2(int);
int main()
{
auto process = [](auto twrap) {
using T = typename decltype(twrap)::type;
std::ofstream writeDat;
std::vector<int> nValues = {26,51,101,201};
for(int i = 0; i< 4; i++){
int N = nValues[i];
Matrix<T> a(N,N);
Matrix<T> b(N,3);
Matrix<T> x = Problem2<T>(N);
std::string sFloat = "2/" + std::to_string(N) + twrap.name() + ".dat";
writeDat.open(sFloat);
for(int i =1; i<N ; i++)
writeDat << i << " " << x(i,1)<<std::endl;
writeDat << N <<" "<< x(N,1)<< std::endl;
writeDat.close();
}
};
for_each_type<double, float>(process);
}
注意:
您可以像这样使for_each_type更可移植(即在c ++ 14上工作):
template<class...Ts, class F>
auto for_each_type(F&& f)
{
#if __cplusplus >= 201703L
(f(type_wrapper<Ts>()),...);
#else
using expand = int[];
expand {
0,
(f(type_wrapper<Ts>()), 0)...
};
#endif
}
答案 1 :(得分:1)
我已经阅读了可变参数模板,但我不知道该如何 在这种情况下应用它:
我相信@RichardHodges可以最充分地回答您的问题。作为参考,如果您希望能够比较variadic template(自C ++ 11起)或fold expression(自C ++ 17起)与{{3} }(这不是唯一的理由),那么您可以使用此代码段,例如:
#include <vector>
#include <fstream>
using namespace std;
// Undefined struct
template <typename T> struct not_available;
// Non-specialized instantiations are not allowed, by using the undefined struct
template <typename T>
constexpr const char* type_string(){ return not_available<T>{}; }
// Specializing for `float`
template <>
constexpr const char* type_string<float>(){ return "Float"; }
// Specializing for `Double`
template <>
constexpr const char* type_string<double>(){ return "Double"; }
// Your classes
template<class T>
struct Matrix
{
Matrix(int, int);
T& operator()(int, int);
};
template<class T> Matrix<T> Problem2(int);
ofstream writeDat;
vector<int> nValues = {26,51,101,201};
// Your routine
template <typename T>
void func()
{
for(int i = 0; i< 4; i++){
int N = nValues[i];
Matrix<T> a(N,N);
Matrix<T> b(N,3);
Matrix<T> x = Problem2<T>(N);
string s = "2/" + to_string(N) + type_string<T>() +".dat";
writeDat.open(s);
for(int i =1; i<N ; i++)
writeDat << i << " " << x(i,1)<<endl;
writeDat << N <<" "<< x(N,1)<< endl;
writeDat.close();
}
}
int main(int argc, char* argv[])
{
func<float>();
func<double>();
return 0;
}
注意:此代码段尝试尽可能地保留原始内容,但由于缺乏足够的理由,我不一定会建议使用全局变量,而不是function template而不是指代带有std::
的名称。