Can I group attributes of one class into one map? - c++

If I have class "node", and wish to include all possible (say int) attributes. Is grouping them into one map good solution.
So instead:
class node{
int color;
int isVisited;
int weight;
public:
};
To have
class node{
map<string, int> property;
public:
setProperty(string property_label, int property_value)
{property[propery_label] = property_value;};
};
int main(){
node n;
n.setProperty("color",int(color::red));
n.setProperty("isVisited", 1);
n.setProperty("weight", 12);
}
EDIT:
The reason to do this is that, when transforming a graph, some local properties (like is visited during some traversal, or is it marked) are needed somewhere in the middle of an algorithm, but these local properties do not represent intrinsic property of a node, and are not needed in the output. Also, sometimes I need more than one "isVisited" variables.
One more reason is to keep the class "node" universal and open for new attributes that eventually might be needed.

The example you gave gives the impression that any node would have all the properties you provided (colour, isVisited, weight). If so it is (usually) better to keep the original class you started with.
There might be a few scenarios in which a map (or possibly rather std::unordered_map) might be superior, though; just a few examples:
You have a large number of possible (but pre-defined) attributes and each node only needs a rather small subset of. Possibly an enum is better suited as key then.
You want/need to store arbitrary attributes unknown at compile time.
Each node has the same attributes, but you mainly access them via user input; then especially an unordered_map could be faster than a (possibly long) if-else-chain.
In the end, all depends on the use case...
For strings as keys possibly a trie might be an interesting alternative, too.

A class (identical to a struct except it defaults to private access rather than public) is primarily to group elements of data and/or functionality together.
You node seems to simply group together three elements. So you probably want to start off with something as simple as:
struct node // access is public by default
{
int color;
int isVisited; // maybe a bool rather than int?
int weight;
}
...
node myNode;
myNode.color = ...
...
std::cout << myNode.weight;

Related

Predefined instances of C++ class enum vs static

I have a class that is a bit complex to initialize. It is basically a tree structure and to create an instance the current constructor takes the root node. Nevertheless there are some instances that will be used more often than others. I would like to make it easier for the user to instantiate this ones faster and easier. I was debating what the best option would be.
First option: using enum to choose between different options in the constructor.
enum CommonPatterns {TRIANGLE, DIAMOND};
typedef struct PatternNode {
int id;
vector<PatternNode*> child;
} PatternNode;
class Pattern {
private:
PatternNode root;
public:
//Constructor that takes the root of the tree
Pattern (PatternNode root) { this->root = root; }
//Constructor that takes enum to create some common instances
Pattern (CommonPatterns pattern)
{
PatternNode predefined_root;
if (pattern == CommonPatterns::TRIANGLE)
{
//Build tree structure for the triangle
}
else if (pattern == CommonPatterns::DIAMOND)
{
//Build tree structure for the diamond
}
Pattern(predefined_root);
}
}
Second option: predifining some static instances
Pattern.h
enum CommonPatterns {TRIANGLE, DIAMOND};
typedef struct PatternNode {
int id;
vector<PatternNode*> child;
} PatternNode;
class Pattern {
private:
PatternNode root;
static Pattern createTriangle();
static Pattern createDiamond();
public:
//Constructor that takes the root of the tree
Pattern (PatternNode root) { this->root = root; }
//Predefined common instances of patterns
const static Pattern TRIANGLE;
const static Pattern DIAMOND;
}
Pattern.cc
Pattern::Pattern createTriangle()
{
PatternNode root;
//Create the tree for the triangle
return Pattern(root);
}
Pattern::Pattern createDiamond()
{
PatternNode root;
//Create the tree for the diamond
return Pattern(root);
}
Pattern Pattern::TRIANGLE = Pattern::createTriangle();
Pattern Pattern::DIAMOND = Pattern::createDiamond();
I don't understand that well the implications of using static performance wise so I would appreciate some suggestions.
As usual when people ask for the performance benefits, the first rule of optimization of code applies: If you think, you have a performance problem, measure the performance.
So my (and many a a people's) opinion is, that you should treat this problem with other things in mind, e.g. what is more clear to the user and/or the reader of the code (which is often yourself, so be extra nice to them!) or what code structure makes it easier to test.
Unfortunately those are a bit up to opinion, so now I will share mine:
Having separate functions for these seems cleaner to me.
It means that for testing purposes you have more but smaller tests, which makes it easier to spot the exact problem, when a test fails.
Related: The constructor is smaller and hence less error prone.
For the user it is extremely specific: He gets a function in the class namespace whose name says what it does.
If you go that route, remember to document these static functions in a way that a user will stumble upon them, e.g. mention them in the class documentation and/or the constructor documentation.
Although the same holds for documentation of the enum.
Lastly let me hazard a guess regarding performance:
Although I don't expect any noticable performance issues either way, the static function version has the advantage that the compiler may optimize it more easily as it (seems to) depends only on compile-time data.
Again to really find out about performance, you would have to
measure the performance differences or --even better--
disassemble the code and see what the compiler actually did with your code.

C++ n-arry tree with different elements

I want to build a n-arry tree from a document. For that i have 3 different types of elements for the tree:
Struct Nodes
Have a name
can contain other Nodes
Depth
Element Node (Leaf of the tree)
Have a Key
Have a value
Depth
Element Template Node (Leaf of the tree)
Have a placeholder which should be resolved later in the program
Depth
At the moment i think about something like this:
class Node {
public:
Node(int depth);
int depth() const;
private:
int depth_;
};
class StructNode : public Node {
...
private:
std::vector<std::unique_ptr<Node>> children;
};
class ElementNode : public Node {
...
};
class ElementTemplateNode : public Node {
...
};
The Tree will be generated from an File on Startup and reused to create an output string like this:
Structname:
key = value
key = value
Structname:
key = value
Structname:
key = value
...
Where the Key and value where directly read from the ElementNode or read from another file with the value of the placeholder inside the ElementTemplateNode
Is there maybe a better Structure for the Tree? Because with the current one i have to check first if its a StructNode, ElementNode or ElementTemplateNode
This is a typical structure for implementing a tree with different kind of nodes. Another variant would be the composite pattern.
The problem that you describe, is usually caused by asking the nodes about what they know, instead of telling them what to do. If you'd do it the other way round (tell, don't ask), you could get rid of those checks and benefit from polymorphism.
The different kind of nodes inherit from Node. You could design your tree using a uniform interface, with virtual functions defined for Node which then can be overridden for the different types of nodes. Calling the method would then do the right things, without need for a manual type check. For generating the output string, you'd tell the root node to generate a string. If it's a structure, it would add the heading and tell its children to generate a string, but if it's a leaf it would just add the key/value pair to the string. No need from outside to know anything about each node.
If the operation of exploring the tree shall not be implemented by the tree itself, the usual approach is to use a visitor pattern. The big advantage is that you write the vistor once, and it's then easy to specialize a new kind of visitor for different algorithms. Again, no need to check the type of the nodes. The pattern makes sure that the right elementary function is called for the right type of node.

What is the best way to initialize a more complex class construct with many unchangeable members in c++

I'm currently designing classes that should represent a chaotic storage system.
Lets say we have slots in rows and columns with certain properties.
So the slots have different restrictions in min/max height, width, length, weight and some more that come from a parameter file.
Also the Slots have a max total weight that must be checked before a new parcel gets added to that slot. And also the max weight that a row of slots can hold is lower than the sum of the max weights of the single slots. So for example each individual slot might be able to hold 50kg but the row of 10 slots must not exceed 200kg, so it is not allowed to fill every slot by 100%. The same is true for the Columns where the maximum weight is lower than the sum of the individual weights of the single rows. The row_id and column_id are atrificial numbers for adressing the slot in the physical system with barcodes or whatever that get read for positioning.
As all this parameters do not change over the lifetime of the program, my intention was to design the classes in a way that this properties are readable by getter functions but there should not be any setter functions (maybe not even private ones) in the object o the values cannot be changed by accident.
There is one class/function that reads the config-file and generates the data structure for the rows and columns with the slots. This function should be able to read the config and create objects for every column holding a row of slots and pass all the values from the config down to the slot.
Later when the program is running I also need some way to search for the best matching slot to add the next parcel or for searching parcels and unload them in a certain sequence.
So the (simplfied) basic structure of the classes would be like this:
Class Parcel {
int width;
int height;
int length;
int weight;
}
Class Slot {
vector<Parcel> parcel;
int min_width;
int max_width;
int min_height;
int max_height;
int min_length;
int max_length;
int max_total_weight;
int act_total_weight;
int total_length;
int free_length;
}
Class Row {
vector<Slot> slot;
int row_id;
int max_total_weight;
int act_total_weight;
}
Class Column {
vector<Row> row;
int column_id;
int max_total_weight;
int act_total_weight;
}
Class Storage {
vector<Column> column;
}
So here are my thoughts about how to initialize the data structure:
First possibility would be to pass all the properties in the constructor(s) of the classes, but then the constructors has some huge parameter lists specially for the Slot class that has a lot of properties.
Second thing that came to my mind (and currently my fafourite way to go) is to use config-data-structures that hold all the parameters. This parameter-objects get filled by the config-function and passed to the constructor when initializing the class. Then it also may be useful to use the parameter class as such and not having all the parameters defined in the storage class once more.
Third way is to use private setter and public getter and make the config class friends with the data structure classes to be able to access the setter functions (but i would prefer to have no setters at all in the final storage structure classes.
Fourth way that i was thinking off, was to derive child classes from the structure classes that hold the setter functions (and also some other logic needed for creating the data structure) so the child has no own variables but only additional functions. So the child class is used to fill the properties but the base class gets added to the data structure vector.
I also want to use Factory pattern to initialize the data structure because the objects have often similar or only slightly different properties. So with the second aproach after creating one row of slots I would maybe want to change the max weight of the slots in that row. Therefore I would need to change the setting in the factory and the factory then fills the parameter data structure differently and passes it to the Slot class. Or is it better to pass the data structure to the factory directly and the factory assigns it but then i think this is not what the factory pattern is meant to be.
I don't know if this is a good aproach or which of the above is best practice.
Or am I missing something and there is a way more convenient solution or this?
Thank you (and sorry if the question is maybe not the way it should be)
When constructing your classes as you describe it you can have a look at the creational design patterns.
Your second proposed solution is almost a builder design pattern. This will help you to construct the Slot e.g. piecewise.
As an example:
#include <iostream>
class Slot {
public:
int GetMinWidth() const { return min_width_; };
int GetMaxWidth() const { return max_width_; };
// Builder class
class SlotBuilder {
public:
SlotBuilder& SetMinWidth(int min_width) {
min_width_ = min_width;
return *this;
}
SlotBuilder& SetMaxWidth(int max_width) {
max_width_ = max_width;
return *this;
}
Slot Build() {
return Slot(min_width_, max_width_);
}
private:
int min_width_{/* you can add default value here*/};
int max_width_{/* you can add default value here*/};
};
// This is optional, but creates a neat interface
static SlotBuilder Create() {
static SlotBuilder slot_builder;
return slot_builder;
}
private:
// Make constructor private to restrict access and force the use of the builder
Slot(int min_width, int max_width) : min_width_(min_width), max_width_(max_width) {}
const int min_width_;
const int max_width_;
// .
// .
// Continue with your const attributes
};
int main() {
// Create the slot with the builder
Slot slot = Slot::Create()
.SetMinWidth(10)
.SetMaxWidth(20)
.Build();
std::cout << slot.GetMinWidth() << ", " << slot.GetMaxWidth();
return 0;
}
You can see the example working here
For having different types that are almost the same a Prototype pattern could work if you want to "clone" a class or in your case a Factory pattern could do the job.
There is never an ideal solution or that one pattern that solves it all, so I can't give you a definitive answer, but here are some collected thoughts:
Default values
Primitive types like int don't have a default value, so make sure you give them one explicitly:
struct Parcel {
int width{};
int height = 0;
int length = {};
int weight{};
}
All those different versions above are equivalent, but you really should use one of them. Otherwise you will probably run into UB down the line.
Const correctness
One thing that I love about C++ and that I dearly miss in languages like C# is const correctness. If you want an object to be immutable, declare it as const. To prevent changes to your objects, either instantiate the object as a const:
const Parcel x;
x.width = 10; // compiler error
or make the members of your classes const:
struct Parcel {
const int width{};
const int height{};
const int length{};
const int weight{};
};
Parcel x;
x.width = 10; // compiler error
Aggregate initialization
If you keep your types simple enough you can initialize the class members with curly braces directly:
const Parcel x { 1, 2, 3, 4 };
In C++ 20, you can also name the members, so this code is equivalent to the line above:
const Parcel x { .width = 1, .height = 2, .length = 3, .weight = 4 };
Note that this can bite you later though if you have to deal with ABI stability and versioning. In that case you are better off using getter and setter functions, because that allows you to still change the data layout of your members.
I have to think about design patterns a bit more. I'll update this post if something useful comes out of it.

Saving in binary files

I've been working on a project for the past few days that involves three linked lists.
Here is an example of the header with the nodes and the lists themselves:
class nodeA
{
int data1;
double data2;
nodeA* next;
}
class listA
{
nodeA* headA;
...
}
class nodeB
{
int data3;
double data4;
nodeB* nextB;
}
class listB
{
nodeB* headB;
...
}
class nodeC
{
int data5;
double data6;
nodeC* nextC;
}
class listC
{
nodeC* headC;
...
}
What i'd like to know is how can i save the lists that i declare in my main so that if i close the program and then open it again i can recover the lists data
So lista_vendas::novaVenda needs to call lista_produto::escolheProduto.
To call lista_produto::escolheProduto you need a lista_produto object. Where are you going to get that lista_produto object from?
There's really only three ways this can be done. I don't know which way is the correct way for you, but I'll list them and you can decide.
1) Have a lista_produto global variable, a global list of products. Then lista_vendas::novaVenda can use the global lista_produto to call lista_produto::escolheProduto. This is the simple solution, but global variables are rightly considered bad style. It also means that you program can only have one list of products, is that a problem? Think carefully before trying this solution.
2) Have a lista_produto as a member variable of lista_vendas or no_vendas. I guessing here but perhaps something like this
class no_vendas
{
public:
unsigned int codigoVenda, dia, mes, ano, numeroItens;
double precoTotal;
lista_produto productList; // list of products
no_vendas* proxi; //referencia para o proximo no
};
Now each vendor has a list of products, which makes sense. So lista_vendas::novaVenda now has access to a lista_produto in each no_vendas and it can use that to call lista_produto::escolheProduto. If this makes sense then this is problably the best solution.
3) Pass a lista_produto as a parameter to lista_vendas::novaVenda. Like this
void novaVenda(unsigned int codigoVenda, lista_produto* productList);
So whatever code calls lista_vendas::novaVenda must also supply the lista_produto that it needs.
As I said I don't know which of these possibilities is correct, because I don't know what you are trying to do (and I don't speak Spanish). But this is a problem in the relationships between your different objects. It's up to you to design your classes so that they can access the different objects that they need to work.
You mentioned inheritance in your title, but this doesn't feel like the right thing to do in this case.
This won't help you with your concrete problem at hand but I think you should use standard containers like std::vector<>. Implementing your own linked list is a nice finger exercise but seldom really necessary. That said, you should use std::vector<no_produto> instead of lista_produto:
#include <vector>
std::vector<no_produto> my_lista_produto;
// fill the vector:
my_lista_produto.push_back(my_no_produto_1);
my_lista_produto.push_back(my_no_produto_2);
// ...
// retrieve one item:
const no_produto &p = my_lista_produto[1];
// clear all items:
my_lista_produto.clear();
A complete list of all available methods can be found here.
Concerning your question: The question title mentions inheritance but there isn't any inheritance used in your example. In order to derive class B from class A you have to write
class A {
public:
void func();
};
class B : public A {
public:
void gunc();
};
This means essentially, B can be treated as an A. B contains the content of A and exposes the public interface of A by itself. Thus we can write:
void B::gunc() {
func();
}
even though B never defines the method func(), it inherited the method from A. I suspect, that you didn't inherit your classes properly from each other.
In addition to my initial thoughts about writing you own linked lists, please consider also composition instead of inheritance. You can find more information about the topic at Wikipedia or on Stack Overflow.

Extending a thrift generated object in C++

Using the following .thrift file
struct myElement {
1: required i32 num,
}
struct stuff {
1: optional map<i32,myElement> mymap,
}
I get thrift-generated class with an STL map. The instance of this class is long-lived
(I append and remove from it as well as write it to disk using TSimpleFileTransport).
I would like to extend myElement in C++, the extenstions should not affect
the serialized version of this object (and this object is not used in any
other language). Whats a clean way to acomplish that?
I contemplated the following, but they didn't seem clean:
Make a second, non thrift map that is indexed with the same key
keeping both in sync could prove to be a pain
Modify the generated code either by post-processing of the generated
header (incl. proprocessor hackery).
Similar to #2, but modify the generation side to include the following in the generated struct and then define NAME_CXX_EXT in a forced-included header
#ifdef NAME_CXX_EXT
NAME_CXX_EXT ...
#endif
All of the above seem rather nasty
The solution I am going to go with for now:
[This is all pseudo code, didn't check this copy for compilation]
The following generated code, which I cannot modify
(though I can change the map to a set)
class GeneratedElement {
public:
// ...
int32_t num;
// ...
};
class GeneratedMap {
public:
// ...
std::map<int32_t, GeneratedElement> myGeneratedMap;
// ...
};
// End of generated code
Elsewhere in the app:
class Element {
public:
GeneratedElement* pGenerated; // <<== ptr into element of another std::map!
time_t lastAccessTime;
};
class MapWrapper {
private:
GeneratedMap theGenerated;
public:
// ...
std::map<int32_t, Element> myMap;
// ...
void doStuffWIthBoth(int32_t key)
{
// instead of
// theGenerated.myGeneratedMap[key].num++; [lookup in map #1]
// time(&myMap[key].lastAccessTime); [lookup in map #2]
Element& el=myMap[key];
el.pGenerated->num++;
time(&el.lastAccessTime);
}
};
I wanted to avoid the double map lookup for every access
(though I know that the complexity remains the same, it is still two lookups ).
I figured I can guarantee that all insertions and removals to/from the theGenerated)
are done in a single spot, and in that same spot is where I populate/remove
the corresponding entry in myMap, I would then be able to initialize
Element::pGenerated to its corresponding element in theGenerated.myGeneratedMap
Not only will this let me save half of the lookup time, I may even change
myMap to a better container type for my keytype (say a hash_map or even a boost
multi index map)
At first this sounded to me like a bad idea. With std::vector and std::dqueue I can
see how this can be a problem as the values will be moved around,
invalidating the pointers. Given that std::map is implemented with a tree
structure, is there really a time where a map element will be relocated?
(my above assumptions were confirmed by the discussion in enter link description here)
While I probably won't provide an access method to each member of myElement or any syntactic sugar (like overloading [] () etc), this lets me treat these elements almost a consistent manner. The only key is that (aside for insertion) I never look for members of mymap directly.
Have you considered just using simple containership?
You're using C++, so you can just wrap the struct(s) in some class or other struct, and provide wrapper methods to do whatever you want.