Как избавится от дублирования кода в шаблоне template?

117
03 марта 2021, 05:10

Всем привет, мне нужно построить код внутри шаблона который тоже будет шаблоном Вот мой код

class A
{
public:
template <typename T1, typename T2>
    A(T1 y, T2 d, T1 t, T2 f, T1 w, T2 l)
    {
     ofstream out;
     out.open(d, ofstream::app);
     out.write((char*)& y, sizeof(y));
     out.close();
     // очередная копия кода
     out.open(f, ofstream::app);
     out.write((char*)& t, sizeof(t));
     out.close();
     // снова копия о боже мой
     out.open(l, ofstream::app);
     out.write((char*)& w, sizeof(w));
     out.close();
    }
};

Как видите он находится внутри класса A и шаблона template используя шаблон я вызываю эту функцию таким способом

int main()
{
    A(777, "1.bin", 666, "2.bin", 555, "3.bin");
}

Проблема в том что мне нужно создать много файлов но я не хочу каждый раз копировать код ofstream.

А так же я не могу использовать код не внутри класса A и шаблона template, все переменные и их работа выполняется только там. Если я перемещаю этот код в отдельный класс он не может передавать прочитанные данные другой переменной или другому классу, получается все работает только внутри класса A и шаблона template. Пытался создать наследования классов но один фиг классы хранят данные только внутри себя и не могут передавать данные между шаблона template. Скорее всего я где то ошибся или чего то не знаю. Надеюсь на подержу и много разных примеров.

Обновления для AlexGlebe

using namespace std;
public:
template <typename T1, typename T2, typename T3, typename T4>
    A(T1 y, T2 d, T1 t, T2 f, T3 w, T4 l, T5 h, T2 r, T3 z, T4 n) {
      ifstream in;
      open_in<T3, T5>(in, y, d);
    // тут начинается другой код который дальше работает с переменными
    // например простой цикл который должен получить данные y и продолжить
    // свое выполнения подсчетов, но к сожалению он получает старые данные
    // которые были добавлены в main
    // A("1.bin", "2.bin", "3.bin", 666, 555, 111, 955635332, 333, 777, 10);
      ofstream out;
      open_out<T1,T2>(out, y,  d);
    }
private :
   // первый сохраняет
    template <typename T1, typename T2>
    void open_out(ofstream & out,T1 a, T2 b) {
              out.open(b, ofstream::app);
              out.write((char*)& a, sizeof(a));
              out.close();
    }
    // второй читаем данные
    template <typename T1, typename T2>
    void open_in(ifstream & in,T1 a, T2 b) {
              in.open(b, ios::binary);
              in.read((char*)& a, sizeof(a)))
              in.close();
    }
};
// main
A("1.bin", "2.bin", "3.bin", 666, 555, 111, 955635332, 333, 777, 10);

Код который читай данные не передает их на переменную y и d в итоге мы получаем старые данные, когда снова попадаем в класс A

И на самом деле я бы хотел вытащить это отдельно от класcа A иначе мне потом сложно будет работать с этим годом.

Answer 1

Может я не понял, но вот мой ответ:

# include <fstream>
class A
{
public:
template <typename T1, typename T2>
    A(T1 y, T2 d, T1 t, T2 f, T1 w, T2 l)
    {
     std::ofstream out;
     openwriteclose<T1,T2>(out, y,  d);
     openwriteclose<T1,T2>(out, t,  f);
     openwriteclose<T1,T2>(out, w,  l);
    }
private :
template <typename T1, typename T2>
  void openwriteclose(std::ofstream & out,T1 y, T2 d){
    out.open(d, std::ofstream::app);
    out.write((char*)& y, sizeof(y));
    out.close();  }
};
int main()
{
    A(777, "1.bin", 666, "2.bin", 555, "3.bin");
}

Второй вариант со списком любого размера :

 # include <fstream>
# include <list>
class A
{
public:
template <typename T1, typename T2>
    A(std::list<std::pair<T1,T2>> & list)
    {
     std::ofstream out;
     for(std::pair<T1,T2> & j : list){
       out.open(j.second, std::ofstream::app);
      out.write((char*)& j.first, sizeof(j.first));
      out.close();    }     
    }
};
int main()
{
  std::list<std::pair<int,char const * > > args={{777, "1.bin"},{ 666, "2.bin"},{ 555, "3.bin"}};
    A a(args);
}
Answer 2

Все варианты, что пришли в голову, как мог написал.

В шаблонах я не эксперт, поэтому variadic templates написал как умел.

Тут на выбор три варианта:

  1. Использовать оператор <<.

  2. Использовать метод write, который возвращает ссылку на объект, и позволяет сделать цепочку вызовов

  3. Variadic templates, почти то что вы хотели.

#include <fstream>
#include <iostream>
#include <string>
class Example{
public:
    template<typename T>
    const Example& write(const T& y, const std::string& d) const{
        std::ofstream out;
        out.open(d, std::ofstream::app);
        out.write(reinterpret_cast<const char*>(&y), sizeof(y));
        out.close();
        return *this;
    }
    struct FilePath{
        std::string filepath;
    };
    template<typename T>
    Example& operator<<(const T& t){
        std::ofstream out;
        out.open(m_filepath, std::ofstream::app);
        out.write(reinterpret_cast<const char*>(&t), sizeof(t));
        out.close();
        return *this;
    }
    Example& operator<<(const FilePath& fp){
        m_filepath = fp.filepath;
        return *this;
    }
    template<typename T>
    struct DataForWriteToFile{
        T data;
        std::string filepath;
    };
    template<typename... Args>
    void writeToFile(Args... args){
        writeToFile(std::forward<Args>(args)...);
    }
    template<typename T, typename... Args>
    void writeToFile(const DataForWriteToFile<T>& t, Args... args){
        write(t.data, t.filepath);
        writeToFile(std::forward<Args>(args)...);
    }
    template<typename T>
    void writeToFile(const DataForWriteToFile<T>& t){
        write(t.data, t.filepath);
    }

private:
    std::string m_filepath = "tmp.bin";
};

int main(){
    Example e;
    using Data = Example::DataForWriteToFile<int>;
    e.write(777, "1.bin").write(666, "2.bin").write(555, "3.bin");
    e << Example::FilePath{"11.bin"} << 777 << Example::FilePath{"22.bin"} << 666 << Example::FilePath{"33.bin"} << 555;
    e.writeToFile(Data{777, "111.bin"}, Data{666, "222.bin"}, Data{555, "333.bin"});
    return 0;
}
Answer 3

Простой вариант с функтором, принимающим два параметра:

#include <fstream>
#include <memory>
#include <type_traits>
#include <utility>
class BatchWrite
{
    public: template<typename Data, typename Path> BatchWrite && 
    operator ()(Data const & data, Path const & path) const
    {
        static_assert(::std::is_standard_layout_v<Data>);
        ::std::ofstream out{};
        out.exceptions(::std::ofstream::badbit bitor ::std::ofstream::failbit bitor ::std::ofstream::eofbit);
        out.open(path, ::std::ofstream::app bitor ::std::ofstream::binary);
        out.write(reinterpret_cast<char const *>(::std::addressof(data)), sizeof(data));
        return ::std::move(*this);
    }
};
int main()
{
    BatchWrite{}(777, "1.bin")(666, "2.bin")(555, "3.bin");
    return 0;
}
READ ALSO
Error: $scope.$watch is not a function Angular 1.6

Error: $scope.$watch is not a function Angular 1.6

Объявляю $watch на переменную, но вылетает эта ошибка:

123
JavaScript. Мгновенная печать

JavaScript. Мгновенная печать

Возможно сделать так, что при открытии html файла, он сразу выводился на печать (в PDF) без данного окна? (изображение ниже)

127
Как удалить элемент без идентификатора

Как удалить элемент без идентификатора

Есть div, который не имеет ни класса, ни id или nameРедактировать html код этого тега нельзя (то есть нельзя приписать ему идентификатор)

93
Python 3 scripts, html [закрыт]

Python 3 scripts, html [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме

86