c++ - 使用可变参数模板改变模板参数

标签 c++ templates

如何分解以下代码,以便可以循环遍历 T = doubleT = 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;
}

最佳答案

使用可变参数扩展来调用包含重复逻辑的模板函数(或可变参数 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);
}

https://godbolt.org/z/w6g6AC

注意:

您可以使 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
}

关于c++ - 使用可变参数模板改变模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52473354/

相关文章:

C++ Windows 窗口是否强制唤醒等待中的线程?

c++ - 递归打印星形图案

c++ - 依赖非类型参数包 : what does the standard say?

c++ - 从函数参数推断模板类型

c++ - 将别名模板传递给它所依赖的模板的基类

C++ 如何释放对外部对象的静态引用?

c++ - 如何在cppunit中捕获异常

c++ - std::any 的 cout vector

c++ - 当模板更改一小部分时共享模板功能的通用功能

c++ - 与错误检查宏一起使用时,带有两个类型参数的模板化函数无法编译