Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
273 views
Welcome To Ask or Share your Answers For Others

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...