There are two kinds of parameterized constraints, one to check if an expression between two operands are allowed, and one for checking a constant value. It’s not legal to put a constraint on non-constant values.

```
template<typename T>
concept bool ParameterizedConstraint = requires (T a, T b)
{
a == b;
a != b;
};
```

The concept `ParameterizedConstraint`

checks if both operations `a == b`

and `a != b`

are defined and allowed. It does *not* check the values of `a`

and `b`

.

The following example contains one subtle mistake. Hint: It will build for any type of `T`

.

```
template<typename T>
concept bool ParameterizedConstraint2 = requires (T a, T b)
{
sizeof(a) == 4;
a == b;
a != b;
};
```

The subtle mistake is `sizeof(a) == 4;`

. The requirement for a parameterized expression is that both operands are constant. Both `sizeof(a)`

and `4`

are constants. What actually is checked is if the equals operator `==`

is defined between two integer types. It does not check if the size of `a`

is 4 bytes!

```
template<typename T>
concept bool ParameterizedConstraint3 = requires (T a, T b)
{
requires sizeof(a) == 4;
a == b;
a != b;
};
```

To check constant values in a requires section, the `requires`

keyword is required. To check for the size, add `requires`

in front of the expression, `requires sizeof(a) == 4;`

.

What is the difference between the following two concepts?

```
template<typename T>
concept bool ParameterizedConstraint4 =
requires
{
4 == 5;
};
```

```
template<typename T>
concept bool ParameterizedConstraint5 =
requires
{
requires 4 == 5;
};
```

The answer is left as an exercise for the reader.

Professional Software Developer, doing mostly C++. Connect with Kent on Twitter.