c++ - 为什么概念细化不能使用简洁的语法

标签 c++ c++-concepts c++20

在提炼概念时,标准中一贯的做法是完整地写出要提炼的概念。例如,在 [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>; }

重要的是概念始终是全函数,这就是不允许关联约束的原因。


请注意,当然可以将“未定义”视为 false 的扩展。出于概念满意度的目的,但这会给包含规则增加额外的皱纹,并且它肯定是不平凡的实现复杂性。当然,某些 future 的标准可能会允许它们。我的 Crystal 球目前在商店里,所以我不能确定。

关于c++ - 为什么概念细化不能使用简洁的语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53684991/

相关文章:

c++ - IAT Hooking,QT库

Android ndk 链接在 libgnuSTL_shared.so 上失败

c++ - 为什么在 C++20 中删除了许多标准库类型的 operator!= ?

c++ - 宇宙飞船运算符(operator)的真实世界使用示例

c++ - 变量的 cstyle 转换返回的值是纯右值还是左值?

c++ - Visual Studio下CMake构建问题

c++ - 在模板类中定义模板化友元函数

c++ - Visual Studio 2019 C++ 对概念的支持 - 编译成功,但出现错误 : Why?

c++ - 使用 C++20 概念将函数参数约束为分配器

scala - 使用 Scala 特征对 C++ 概念进行建模