Шаблоны C ++, содержащие std :: vector

0

Совсем недавно я написал класс, содержащий четыре функции для открытия и чтения многоколоночных файлов данных (до 4 столбцов). В функции имя файла, который нужно открыть "имя_файла", передается из основной программы в функцию в классе "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;
}
Теги:
class
templates
vector

2 ответа

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) {
        ...
    }
}

и это будет шаблонный метод класса.

  • 0
    Я полагаю, это хороший момент. По окончании класс будет содержать четыре функции, а не только одну, поэтому я записал это в класс как метод организации их вместе. Однако поскольку свойства, вероятно, никогда не потребуют применения наследования или полиморфизма и одна функция не зависит от другой, может быть лучше просто записать четыре функции в один файл для организационных целей, а не помещать их в класс.
  • 0
    Однако, независимо от того, как это написано, я все равно получаю следующую ошибку. "Read_Columnar_File <float> :: Read_One_Column (std :: __ 1 :: basic_string <char, std :: __ 1 :: char_traits <char>, std :: __ 1 :: allocator <char>> const &, std :: __ 1 :: vector <float, std :: __ 1 :: allocator <float>> &) ", на который ссылается: _main в main.o ld: символы не найдены для архитектуры x86_64 clang: error: сбой команды компоновщика с кодом выхода 1 (использовать -в, чтобы увидеть вызов)
Показать ещё 4 комментария
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();
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню