Hello, I have a problem with data serialization. In the previous topic I didn’t open the question badly, I decided to remove it and re-formulate it. By assignment, I have to make my container look like a map<key,value> in which the key goes to the tree, and the value to the file whose name is the key.

For this part of the assignment, we were told to use the predefined trait classes: KeySerializationTrait, FileTypeSerializationTrait.

 template <typename T> struct KeySerializationTrait { static std::string Serialize(const T& t) { std::stringstream ss; ss << t; return ss.str(); } static T Deserialize(const std::string& str) { T tmp; std::stringstream(str) >> tmp; return tmp; } }; template <typename T> struct FileTypeSerializationTrait { static void Serialize(std::ostream& fileStream, const T& item) { fileStream << item; } static T Deserialize(std::istream& fileStream) { T tmp; fileStream >> tmp; return tmp; } }; template <> struct FileTypeSerializationTrait <std::string> { static void Serialize(std::ostream& fileStream, const std::string& str) { fileStream << str; } static std::string Deserialize(std::istream& fileStream) { return std::string((std::istreambuf_iterator<char>(fileStream)), std::istreambuf_iterator<char>()); }; }; 

The assignment states that the container user must provide suitable serialization and deserialization of its data types in the form of template specialization.

The problem is that I don't understand what that means.

For example, if I want to write a function in the tree to save a variable to a file, how do I use these templates?

The tree has templates, where Key is the type of the key, and mapped_type is the type of the variable (which I must save to the file):

my code is getValue tree, there is getValue and setValue .

 struct Tree_ // структура для представления узлов дерева { Key key; unsigned char height; Tree_* parent; Tree_* left; Tree_* right; Tree_(Key k) { key = k; left = right = parent = 0; height = 1; } //читает с файла mapped_type getValue() { // как я понимаю, сюда нужно добавить эти структуры, но когда я их инициирую в классе, компилятор их не видит в структуре. return key; } //запись в файл bool setValue(mapped_type a) { return true; } }; 

Update :: I tried to implement het and set. At the moment they look like this:

  mapped_type getValue() { FileTypeSerializationTrait<mapped_type> FileTypeSerialization; std::ifstream ifs(getFileName(key));//getFileName это перевод кея в стринг mapped_type tmp= FileTypeSerialization.Deserialize(ifs); ifs.close(); return tmp; } void setValue(mapped_type a) { FileTypeSerializationTrait<mapped_type> FileTypeSerialization; std::ofstream ofs(getFileName(key));//getFileName это перевод кея в стринг FileTypeSerialization.Serialize(ofs, a); ofs.close(); } 

The question is, do I use them correctly?

  • I think you still lack the integrity of the above code so that people here can understand it and recommend something. It is not clear that for the type AVL_Tree , it is not clear how Tree_ interconnected with the code above, and, most likely, the structure is also template, it has some Key and mapped_type , although they are not specified. - AivanF.
  • And this construct, template <> struct FileTypeSerializationTrait <std::string> , allows you to define special behavior for specific template types. In your case, the reason for this is a special form of reading the string in Deserialize . - AivanF.
  • I have forgiven the question even more, reducing everything to how to get a record in getValue and in setValue using these templates. - Demolver

1 answer 1

Your task is:

By assignment, I have to make my container look like a map, in which the key goes to the tree, and the file goes to a file whose name is the key.

And now your code does it. Translates a key into a string, saves, loads it. But I would not endure getFileName separately. In addition, you do not need to create instances of structures - their static methods.

  mapped_type getValue() { std::ifstream ifs(KeySerializationTrait<Key>::Serialize(key)); mapped_type tmp= FileTypeSerializationTrait<mapped_type>::Deserialize(ifs); ifs.close(); return tmp; } void setValue(mapped_type a) { std::ofstream ofs(KeySerializationTrait<Key>::Serialize(key)); FileTypeSerializationTrait<mapped_type>::Serialize(ofs, a); ofs.close(); } 

By the way, as I understand it, you did not use KeySerializationTrait::Deserialize . As I understand it, you will need this method after serializing the tree itself, and not just its nodes. That is, when the tree is serialized, the nodes are saved to files, then the keys are in a separate file. And during deserialization, keys are first read, converted to the necessary type, then the node values ​​from their files.

  • @Demolver please :) - AivanF.