首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用可变模板改变模板参数

使用可变模板改变模板参数
EN

Stack Overflow用户
提问于 2018-09-24 13:51:29
回答 2查看 86关注 0票数 2

如何分解以下代码,以便在T = doubleT = float中执行循环?我读过关于可变模板的文章,但我不知道如何在这种情况下应用它:

代码语言:javascript
复制
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;
}
EN

回答 2

Stack Overflow用户

发布于 2018-09-24 16:00:39

使用可变扩展来调用包含复制逻辑的模板函数(或可变lambda):

代码语言:javascript
复制
#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);
}

https://godbolt.org/z/w6g6AC

注意:

你可以像这样让for_each_type变得更便携(即在c++14上工作):

代码语言:javascript
复制
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
}
票数 2
EN

Stack Overflow用户

发布于 2018-09-24 15:38:53

我读过关于可变模板的文章,但我不明白如何在这种情况下应用它:

我相信@RichardHodges已经很好地回答了你的问题。作为参考,如果您希望能够将使用 (因为C++11)或 (因为C++17)的方式与仅使用的方式进行比较(并不是说这样做有特殊的原因),那么您可以使用下面的代码片段:

代码语言:javascript
复制
#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;
}

注意:这段代码试图尽可能多地使用原始代码,但由于缺乏足够好的理由,我不建议使用全局变量,也不建议使用opting for using namespace std而不是使用std::引用名称。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52473354

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档