- A+

When refining concepts, the way it is consistently done in the standard is to fully write out the concept being refined. For instance, in [concepts.integral], `SignedIntegral`

refines `Integral`

like so:

`template<class T> concept Integral = is_integral_v<T>; template<class T> concept SignedIntegral = Integral<T> && is_signed_v<T>; `

Why can't the refined concept be written as:

`template<Integral T> concept SignedIntegral2 = is_signed_v<T>; `

`SignedIntegral2`

seems to have the same obvious meaning of `SignedIntegral`

, but it doesn't even compile on clang. Is there a reason for this?

The declaration of `SignedIntegral2`

is ill-formed because of [temp.concept]/4:

A concept shall not have associated constraints.

And it's important to understand the reason for this. Concepts are basically predicates. Their job is to take a series of arguments (most commonly, a series of types) and say whether the concept is satisfied or not. But consider what answer these two different implementations would give:

`SignedIntegral<int32_t>`

is`true`

`SignedIntegral<uint32_t>`

is`false`

`SignedIntegral<string>`

is`false`

But:

`SignedIntegral2<int32_t>`

is`true`

`SignedIntegral2<uint32_t>`

is`false`

`SignedIntegral2<string>`

is... undefined

The whole point of concepts is to constrain. The proposed alternative, terse declaration in `SignedIntegral2`

*constrains* the type parameter `T`

to be `Integral`

. Since `string`

does not satisfy `Integral`

, we cannot even ask the question of if it's a `SignedIntegral2`

.

Put a different way, `SignedIntegral`

is a total function but `SignedIntegral2`

is a partial function that is only defined on `Integral`

types. This might be more clear if we write both to actually be functions:

`template <typename T> constexpr bool SignedIntegral() { return Integral<T> && is_signed_v<T>; } template <Integral T> constexpr bool SignedIntegral2() { return is_signed_v<T>; } `

It is important that concepts always be total functions, which is why associated constraints are disallowed.

Note that it is surely possible as an extension to treat "undefined" as `false`

for the purposes of concepts satisfaction, but this would add extra wrinkles to the subsumption rules and it's surely non-trivial implementation complexity. It's certainly possible that some future standard might allow them. My crystal ball is currently at the shop, so I can't say for sure.