Named Requirements are a summary of what the STL expects for certain classes/types to be passed to functions as an argument. Understanding these are important for writing code that works well with other functions in the STL. There are many places you can read them on, but I personally prefer Cppreference. Let's take the following statement as an example.
Compare functions should return
falsewhen the two values are equal
This is explicitly stated on the named requirement named Compare, the parts that state this are as follows:
comp, an object of type
T, For all
From this we can see that objects of type
T, when called as
f(a,a), should return
false. Obviously the two
as are equal, and we can expect that the STL functions may (or in this case, will) spit unexpected errors if the requirement given in the statement is not satisfied.
The above was an example of named requirements, from a statement relatively well-known in CP. And in this example you can see that following the named requirements is very, very important.
Now we need to understand exactly how we should read the named requirements. There are many different named requirements, and not all named requirements' descriptions look the same. Noticing the difference before understanding them is helpful, so I shall explain what is different in these requirements.
- Some requirements have a very "short and concise" description.
The Predicate requirement is a good example of this. Let's see the description of the requirement, and try to understand it.
The Predicate requirements describe a callable that returns a value testable as a bool.
A good way to understand such descriptions is cutting them phrase by phrase. We can apply this method to this description like this.
"The Predicate requirements describe..."
- a callable means that this requirement includes the Callable requirement
- that returns a value means that the return type of the call is not void
- testable as a bool means that the returned type, either is bool, or can be contextually converted into a bool-type value. the types that fit this condition include
long, and most importantly
- Some requirements have an "organized table" in its description.
The UniformRandomBitGenerator requirement is a good example. In its description you can clearly see (with the table) what functions/expressions you need to implement for this requirement. The table provides information on what methods it requires, what return types they need to have, and extra requirements needed to fit the requirement.
(Red = The members you need to implement, Blue = Their return types, Green = Implementation details about the members. most other descriptions have a table with a similar format as well.)
- Some requirements have a "dependency" in its description.
The named requirements for iterators show this "dependency" well. Basically when we say
Tsatisfies A if ... the type
Tsatisfies B, ...
Then the named requirement "A" has the named requirement "B" as a prerequisite. Therefore to implement a type satisfying A, it would be convenient to implement methods for B first.
These three are the ways how (at least I thought) named requirements are described. It would be good practice to try these methods on other named requirements, or come up with your own way to read them as well. This was the part 1 of "Understanding Named Requirements", and in part 2 I will demonstrate making an actual working class based on the RandomNumberEngine requirement as a practice for understanding the descriptions. Stay tuned!