Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't concept refinement use the terse syntax

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?

like image 630
Barry Avatar asked Dec 08 '18 17:12

Barry


1 Answers

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.

like image 150
Barry Avatar answered Nov 12 '22 13:11

Barry