Type and implicit conversion constraints

By , last updated June 23, 2019

Type constraints

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 constraints

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.