Simple Requirements on the Interface
Get an overview of the simple requirements on the interface.
Let’s think about operations for a little longer. What does it mean to require the support of a +
operation?
Constrain the accepted types
It means that we constrain the accepted types to those that have a function T T::operator+(const T& other) const
. It can be T T::operator+(const U& other) const
as well because maybe we want to add to an instance of another type later on, but that’s not the point here. The important point is that we made a requirement on having a specific function.
We should be able to define a requirement on any function call. Let’s see how to do it.
Note: Try uncommenting line 36 and run the code again to see an unsatisfied constraints error.
#include <iostream>#include <string>#include <concepts>template <typename T> // 2concept HasSquare = requires (T t) {t.square();};class IntWithoutSquare {public:IntWithoutSquare(int num) : m_num(num) {}private:int m_num;};class IntWithSquare {public:IntWithSquare(int num) : m_num(num) {}int square() {return m_num * m_num;}private:int m_num;};void printSquare(HasSquare auto number) { // 1std::cout << number.square() << '\n';}int main() {printSquare(IntWithSquare{5});// printSquare(IntWithoutSquare{4});}
In this example, we have a function printSquare
that requires a parameter that satisfies the concept HasSquare
. In that concept, we’ve defined what interface we expect. After the requires
keyword, we write the function calls that should be supported by the interface of the accepted types.
We write our expectations after the requires
keyword. First, there is a parameter list between parentheses (like for a function) where we list all the template parameters that we want to be constrained and any other parameters that might appear in the constraints. We’ll discuss more on that later in the course.
Constraint on an instance of T
template type
If we expect that any passed-in type has a function called square
, we’ll write ...