包含std :: vector的C ++模板

时间:2014-11-09 20:28:27

标签: c++ class templates vector

最近我写了一个包含四个函数的类来打开和读取多列数据文件(最多4列)。在该函数中,要打开的文件名“file_name”从主程序传递到类“Read_Columnar_File”中的函数。使用std :: vector读入数据并传回主程序。但是,它要求程序员在每次使用时更改输入列的数据类型,这是错误的处方。文件名将始终是一个字符串,因此不需要模板化;但是,使用向量读入的数组的数据类型可能会发生变化,因此需要进行通用模板化。我正在尝试将类转换为模板类,并且在制作包含std :: vector的模板方面缺少对该过程的一些基本理解。为了简化开发过程,我回到了类中的一个名为“Read_One_Column”的例程,并尝试将其转换为数据类型标记为Type1的模板。我认为我的问题在于语法,因为调试器告诉我主程序中的命令是未定义的。任何建议,以帮助纠正这一点将不胜感激。下面附有现有代码的副本。

#include <vector>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <iterator>

template <class Type1> class Read_Columnar_File {
public:
    void Read_One_Column(const std::string& file_name,std::vector<Type1>& Column1);
};

template <class Type1> void Read_Columnar_File<Type1>::Read_One_Column(const std::string& file_name,
                                                                       std::vector<Type1>& Column1)
{
    std::ifstream inp(file_name,std::ios::in | std::ios::binary);
    std::istream_iterator<Type1> start((inp)), end;
    if(inp.is_open()) {
    Column1.assign(start,end);
}
    else std::cout << "Cannot Open " << file_name << std::endl;
    inp.close();
}

int main(int argc, const char * argv[]) {
    int i;
    std::vector<float> str1;
    Read_Columnar_File<float> ob1;

    char str[20];
    std::strcpy(str,"Test.txt");

    ob1.Read_One_Column(str,str1);

    for(i=0; i < 7; i++) std::cout << str1[i] << std::endl;

    return 0;
}

2 个答案:

答案 0 :(得分:1)

语法更简单:

template <typename Type1>
void Read_One_Column(const std::string& file_name,
                     std::vector<Type1>& Column1) {
    ...
}

根本不需要创建一个类(它只是一个模板函数)。

如果由于其他原因需要将函数放在类中,那么语法是相同的

struct Read_Columnar_File {
    ...
    template<typename Type1>
    void Read_One_Column(const std::string& file_name,
                         std::vector<Type1>& Column1) {
        ...
    }
}

它将是该类的模板方法。

答案 1 :(得分:0)

为了完全结束这个问题,我发布了最终正确的代码,因为我相信其他人将来会有同样的问题,我希望这有助于他们。要回答我的问题,在编写模板时,整个算法需要包含在标头中,并且不能在标头和实现文件之间进行拆分。该程序是一种从输入文件中读取柱状数据的非常通用的方法,并假设每列数据的长度与其他数据相同。用户只需将头文件与其主程序一样,指定矢量定义中每列的数据类型并读入数据。主程序如下所示。该版本允许用户调用4种不同的功能,这些功能可用于读取多达四列数据。

    #include <vector>
    #include <iostream>
    #include <cstring>
    #include "Read_Columnar_File.h"

    int main(int argc, const char * argv[]) {
        char str[20];
        strcpy(str,"Test.txt");

        // - Format for reading in a single column of data
        //   Data in this case is declared as a float in
        //   the vector, but it can be any data type
        /*
        std::vector<float> str2;
        Read_One_Column(str,str2);
        */

        // - Format for reading in two columns of data from
        //   an input file
        /*
        std::vector<float> str2;
        std::vector<int> str3;
        Read_Two_Columns(str,str2,str3);
         */

        // - Format for reading in three columns of data from
        //   an input file
        /*
        std::vector<float> str2;
        std::vector<int> str3;
        std::vector<int> str4;
        Read_Three_Columns(str,str2,str3,str4);
         */

        std::vector<float> str2;
        std::vector<int> str3;
        std::vector<int> str4;
        std::vector<float> str5;
        Read_Four_Columns(str,str2,str3,str4,str5);

        return 0;
    }

The implementation file is shown below.

    #include <vector>
    #include <stdio.h>
    #include <fstream>
    #include <iterator>

    template <class X> void Read_One_Column(const std::string& file_name,std::vector<X>& Column1)
    {
        std::ifstream inp(file_name,std::ios::in | std::ios::binary);
        std::istream_iterator<X> start((inp)), end;
        if(inp.is_open()) {
            Column1.assign(start,end);
        }
        else std::cout << "Cannot Open " << file_name << std::endl;
        inp.close();
    }

    template <class X,class Y> void Read_Two_Columns(const std::string& file_name,std::vector<X>& Column1,
                                            std::vector<Y>& Column2)
    {
        int i;
        X Col1;
        Y Col2;
        std::ifstream inp(file_name,std::ios::in | std::ios::binary);
        if(inp.is_open()){
        for(i=0; i < 7; i++){
                inp >> Col1 >> Col2;
                Column1.push_back(Col1), Column2.push_back(Col2);
            }
        }
        else std::cout << "Cannot Open " << file_name << std::endl;
        inp.close();
     }

    template <class X,class Y, class Z> void Read_Three_Columns(const std::string& file_name,std::vector<X>& Column1,
                                                                std::vector<Y>&     Column2,std::vector<Z>& Column3
    {
        int i;
        X Col1;
        Y Col2;
        Z Col3;
        std::ifstream inp(file_name,std::ios::in | std::ios::binary);
    if(inp.is_open()){
        for(i=0; i < 7; i++){
            inp >> Col1 >> Col2 >> Col3;
            Column1.push_back(Col1), Column2.push_back(Col2), Column3.push_back(Col3);
        }
    }
    else std::cout << "Cannot Open " << file_name << std::endl;
    inp.close();
}

template <class X,class Y, class Z,class A> void Read_Four_Columns(const std::string& file_name,std::vector<X>& Column1,
                                                            std::vector<Y>& Column2,std::vector<Z>& Column3,
                                                            std::vector<A>& Column4)
{
    int i;
    X Col1;
    Y Col2;
    Z Col3;
    A Col4;
    std::ifstream inp(file_name,std::ios::in | std::ios::binary);
    if(inp.is_open()){
        for(i=0; i < 7; i++){
            inp >> Col1 >> Col2 >> Col3 >> Col4;
            Column1.push_back(Col1), Column2.push_back(Col2),
            Column3.push_back(Col3), Column4.push_back(Col4);
        }
    }
    else std::cout << "Cannot Open " << file_name << std::endl;
    inp.close();
}