为什么概念细化不能使用简洁的语法
Why can't concept refinement use the terse syntax
提炼概念时,标准中一贯的做法是完整地写出要提炼的概念。例如,在 [concepts.integral] 中,SignedIntegral
像这样优化 Integral
:
template<class T>
concept Integral = is_integral_v<T>;
template<class T>
concept SignedIntegral = Integral<T> && is_signed_v<T>;
为什么细化的概念不能写成:
template<Integral T>
concept SignedIntegral2 = is_signed_v<T>;
SignedIntegral2
似乎与 SignedIntegral
具有相同的明显含义,但它甚至无法在 clang 上编译。这有什么原因吗?
SignedIntegral2
的声明格式错误,因为 [temp.concept]/4:
A concept shall not have associated constraints.
了解其中的原因很重要。概念基本上是谓词。他们的工作是接受一系列论证(最常见的是一系列类型)并说明这个概念是否得到满足。但是考虑一下这两种不同的实现会给出什么答案:
SignedIntegral<int32_t>
是 true
SignedIntegral<uint32_t>
是 false
SignedIntegral<string>
是 false
但是:
SignedIntegral2<int32_t>
是 true
SignedIntegral2<uint32_t>
是 false
SignedIntegral2<string>
是...未定义
概念的全部意义在于约束。 SignedIntegral2
中提议的替代简洁声明将类型参数 T
约束为 Integral
。由于 string
不满足 Integral
,我们甚至不能问它是否是 SignedIntegral2
的问题。
换句话说,SignedIntegral
是一个全函数,而 SignedIntegral2
是一个只在 Integral
类型上定义的偏函数。如果我们把两者都写成函数,这可能会更清楚:
template <typename T>
constexpr bool SignedIntegral() { return Integral<T> && is_signed_v<T>; }
template <Integral T>
constexpr bool SignedIntegral2() { return is_signed_v<T>; }
重要的是概念始终是全函数,这就是不允许关联约束的原因。
请注意,出于概念满意度的目的,将 "undefined" 视为 false
的扩展当然是可能的,但这会给包含规则增加额外的皱纹,而且这肯定是不平凡的实施复杂性。未来的某些标准肯定有可能允许它们。我的 crystal 球目前在店里,所以我不能确定。
提炼概念时,标准中一贯的做法是完整地写出要提炼的概念。例如,在 [concepts.integral] 中,SignedIntegral
像这样优化 Integral
:
template<class T>
concept Integral = is_integral_v<T>;
template<class T>
concept SignedIntegral = Integral<T> && is_signed_v<T>;
为什么细化的概念不能写成:
template<Integral T>
concept SignedIntegral2 = is_signed_v<T>;
SignedIntegral2
似乎与 SignedIntegral
具有相同的明显含义,但它甚至无法在 clang 上编译。这有什么原因吗?
SignedIntegral2
的声明格式错误,因为 [temp.concept]/4:
A concept shall not have associated constraints.
了解其中的原因很重要。概念基本上是谓词。他们的工作是接受一系列论证(最常见的是一系列类型)并说明这个概念是否得到满足。但是考虑一下这两种不同的实现会给出什么答案:
SignedIntegral<int32_t>
是true
SignedIntegral<uint32_t>
是false
SignedIntegral<string>
是false
但是:
SignedIntegral2<int32_t>
是true
SignedIntegral2<uint32_t>
是false
SignedIntegral2<string>
是...未定义
概念的全部意义在于约束。 SignedIntegral2
中提议的替代简洁声明将类型参数 T
约束为 Integral
。由于 string
不满足 Integral
,我们甚至不能问它是否是 SignedIntegral2
的问题。
换句话说,SignedIntegral
是一个全函数,而 SignedIntegral2
是一个只在 Integral
类型上定义的偏函数。如果我们把两者都写成函数,这可能会更清楚:
template <typename T>
constexpr bool SignedIntegral() { return Integral<T> && is_signed_v<T>; }
template <Integral T>
constexpr bool SignedIntegral2() { return is_signed_v<T>; }
重要的是概念始终是全函数,这就是不允许关联约束的原因。
请注意,出于概念满意度的目的,将 "undefined" 视为 false
的扩展当然是可能的,但这会给包含规则增加额外的皱纹,而且这肯定是不平凡的实施复杂性。未来的某些标准肯定有可能允许它们。我的 crystal 球目前在店里,所以我不能确定。