Hi I am new to C++ and I am trying to create a class hierarchy where each class represents a node in a schema document, think json-schema. Have a look at the representation of e.g. a string. A string can have three optional constraints
min_lengthmax_lengthpattern
Furthermore a string is a type so it would make sense to have a base class representing a type from which all types (boolean, number, ...) inherit. Now, one way to achieve this is by writing something like
struct Type { const std::string m_name; Type(const std::string& name) : m_name{name} {} virtual X Serialize() const { //... } }; struct String : Type { const int m_max_len; const int m_min_len; const std::string m_pattern; String(int min_len, int max_len, const std::string& pattern) : Type("string") , m_min_len(min_len) , m_max_len(max_len) , m_pattern(pattern) {} X Serialize() const override { // If min_length was not set then it should be omitted from the serialized output. } }; This String implementation would not make the constraints optional. What to do?
Options:
- One could employ a strategy where the default constructor parameters where set to some "illegal" value like
INT_MIN(which would work in this case because the length can not be negative) but that would not work in the general case. It could very well be that all possible integers a legal values, the same goes for thepatternparameter. - You do not want to have different constructors for every possible permutation of optional parameters. In this case there are three optional values which would yield
2^3different constructors. Also it would not be possible for the compiler to distinguish between the constructorsString(int min_length)andString(int max_length). - It would be possible to do something like
String(int* min_length = nullptr, int* max_length = nullptr, const std::string* nullptr)
but then you would have to usenew/deleteor give lvalues for the set parameters. - Finally each member could be a
std::unique_ptr.
String(std::unique_ptr<int> min_value nullptr, std::unique_ptr<int> max_value = nullptr, std::unique_ptr<const std::string> pattern = nullptr)
but then you would end up with quite complicated calls when creating an instance ofString. Also if implementing a container ofTypes which may have optional parameters of its own things quickly get out of hand.
Finally, the code must be compatible with C++14.
unsignedintegers, not plainint.String(MinLength::default(),MaxLength(42),string). Also you might find inspiration in this blog or this.Typerelevant to your question? When I skip the parts of your question that refer to your type hierarchy, it makes as much sense as when I read the whole thing. It seems like this question should be focused on your class with optional parameters, to the exclusion of polymorphism. The one relevant detail I see hidden in the polymorphism discussion is a mention that you need to distinguish between "parameter not given" and "given parameter imposes no restrictions" (an example of the latter would be setting the min length to 0). You might want to mention that detail in the text.