Type constraints restrict by limiting the type accepted. By this you can only accept types, which contain some properties or a set of subtypes.

Variable concept:

```
template<typename T>
concept bool TypeHasTypeVar = requires { typename T::type; };
```

Function concept:

```
template<typename T>
concept bool TypeHasTypeFn ()
{
return requires { typename T::type; };
}
```

The previous concepts requires the type `T`

to have a subtype `::type`

, such that when replacing `T`

in `T::type`

yields a valid type.

The struct `foo_type`

has a C++11 *typedef*, also known as a `using`

. It introduces a new type called `type`

in `foo_type`

.

```
struct foo_type
{
using type = int;
};
```

Replacing `T`

in `T::type`

where `T = foo_type`

, will yield a valid type. `foo_type::type`

is a valid type, and compilation may resume because this constraint is satisfied.

If you were a library author, you can use type constraints to get early error messages for your users if their user supplied types does not implement the required set of types.

Most STL containers have a `key_type`

and `value_type`

. If you require such type, you can require it with a type constraint.

Implicit conversion checks if a operation between two concepts result in an other type without specifying the type explicitly.

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

The comparison `a == b`

must yield a boolean value.

```
template<typename T>
concept bool ImplicitBoolFn()
{
return requires(T a, T b)
{
{ a == b } -> bool;
};
};
```

`ImplicitBoolVar`

and `ImplicitBoolFn`

have identical semantics, only difference is the first one is implemented as a *variable concept*, and the second one as a *function concept*.

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