为什么概念优化不能使用简洁的语法

时间:2018-12-08 17:18:12

标签: 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上编译。有这个原因吗?

1 个答案:

答案 0 :(得分:18)

由于[temp.concept]/4SignedIntegral2的声明格式错误:

  

一个概念不应有关联的约束。

理解这一点的原因很重要。概念基本上是谓词。他们的工作是接受一系列参数(最常见的是一系列类型),并说出该概念是否得到满足。但是请考虑这两种不同的实现将给出什么答案:

  • SignedIntegral<int32_t>true
  • SignedIntegral<uint32_t>false
  • SignedIntegral<string>false

但是:

  • SignedIntegral2<int32_t>true
  • SignedIntegral2<uint32_t>false
  • SignedIntegral2<string>是...未定义

概念的全部要点是约束。 SignedIntegral2中建议的替代性简洁声明约束类型参数TIntegral。由于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作为扩展,但这会给使用规则带来更多的麻烦,并且实现的复杂性肯定是不平凡的。将来某些标准可能会允许它们。我的水晶球目前在商店里,所以我不能肯定地说。