概念和模板约束之间有什么区别?
我想知道C ++完整概念提案和模板约束(例如,Dlang中出现的约束或C ++ 1y的新概念精简build议 )之间的语义差异。
什么是比模板约束能做的完整概念不能做到的?
以下信息已过时。 它需要根据最新的Concepts Lite草案进行更新。
约束提议的第3部分涵盖了这个问题的合理深度。
这个概念提案已经在短时间内被放在了后面的燃烧器上,希望能够在更短的时间范围内实现约束(即概念 – 概念),而目前的目标至less是C ++中的某些东西。 这个约束build议被devise成向后面的概念定义的平滑过渡。 制约因素是概念提案的一部分,是其定义中必不可less的组成部分。
在C ++ ,Sutton和Stroustrup 的概念库devise中 ,考虑以下关系:
概念=约束+公理
要快速总结其含义:
- 约束 – 一个静态可评估的属性types的谓词。 纯粹的句法要求。 不是域抽象。
- 公理 – 假定为真的types的语义要求。 没有静态检查。
- 概念 – 一般,对其参数的algorithm的抽象要求。 用约束和公理来定义。
所以,如果你添加公理(语义属性)的约束(语法属性),你会得到概念。
概念 – 精简版
概念精简的build议只给我们带来了第一部分的约束,但这是走向完整概念的一个重要的必要步骤。
约束
约束都是关于语法的 。 它们给了我们一种在编译时静态辨别types属性的方法,以便我们可以根据它们的语法属性限制用作模板参数的types。 在当前的约束build议中,它们用命题演算的一个子集来表示,使用逻辑连接词如&&
和||
。
让我们来看看一个行动的约束:
template <typename Cont> requires Sortable<Cont>() void sort(Cont& container);
这里我们定义了一个名为sort
的函数模板。 新增加的是要求条款 。 require子句为该函数的模板参数提供了一些约束。 特别是,这个约束表示typesCont
必须是一个Sortable
types。 一个整洁的事情是,它可以写成一个更简洁的forms:
template <Sortable Cont> void sort(Cont& container);
现在,如果您尝试将不被视为可Sortable
任何内容传递给此函数,您将得到一个很好的错误,并立即告诉您为T
推导的types不是可Sortable
types。 如果你已经在C ++ 11中完成了这个工作,那么在sort
函数里面会有一些可怕的错误,这对任何人都是没有意义的。
约束谓词与types特征非常相似。 他们采取一些模板参数types,并给你一些关于它的信息。 约束条件试图回答关于types的以下几种问题:
- 这个types是否有这样的运算符重载?
- 这些types可以用作操作符吗?
- 这种types有这样的特质吗?
- 这个常数expression式等于那个吗? (对于非types的模板参数)
- 这个types是否有一个叫做yada-yada的函数返回这个types?
- 这个types是否满足所有的语法要求?
但是,限制并不意味着取代types特征。 相反,他们将携手并进。 现在可以根据概念和types特征来定义一些types特征。
例子
所以关于约束的重要之处在于他们不关心一个iota的语义。 约束的一些很好的例子是:
-
Equality_comparable<T>
:检查相同types的两个操作数是否具有==
types。 -
Equality_comparable<T,U>
:检查给定types的左右操作数是否存在==
-
Arithmetic<T>
:检查types是否是算术types。 -
Floating_point<T>
:检查types是否为浮点types。 -
Input_iterator<T>
:检查types是否支持input迭代器必须支持的语法操作。 -
Same<T,U>
:检查给定types是否相同。
你可以用一个特殊的概念构buildGCC来尝试所有这些。
超越Concepts-Lite
现在我们进入超越概念提案的一切。 这比未来本身更加未来主义。 从这里开始的一切都可能会发生很大的变化。
公理
公理都是关于语义的 。 它们指定了关系,不variables,复杂性保证等等。 我们来看一个例子。
虽然Equality_comparable<T,U>
约束会告诉你有一个operator==
需要typesT
和U
,但它并不告诉你这个操作是什么意思 。 为此,我们将有公理Equivalence_relation
。 这个公理说,当这两种types的对象与operator==
相比较时,这些对象是等价的。 这可能看起来多余,但肯定不是。 你可以很容易地定义一个operator==
,而不像operator<
。 你会做坏事,但你可以。
另一个例子是一个Greater
公理。 说T
型的两个对象可以与“和<
操作符进行比较是好的,但它们是什么意思 ? Greater
公理说,如果x
大于y
,那么y
小于x
。 拟议的规范如此公理如下:
template<typename T> axiom Greater(T x, T y) { (x>y) == (y<x); }
因此,公理回答以下几类问题:
- 这两个运营商是否有这种关系?
- 这种types的操作符是否意味着这个?
- 这种types的操作是否有这种复杂性?
- 这个操作符的结果是否意味着这是真的?
也就是说,他们完全关心这些types的types和操作的语义。 这些东西不能被静态检查。 如果这需要检查,一个types必须以某种方式宣布它遵守这些语义。
例子
这里有一些公理的例子:
-
Equivalence_relation
:如果两个对象比较==
,则它们是等价的。 -
Greater
:只要x > y
,那么y < x
。 -
Less_equal
:当x <= y
,则!(y < x)
。 -
Copy_equality
:对于typesT
x
和y
:如果x == y
,通过复制构造T{x} == y
创build的同一types的新对象仍然是x == y
(即它是非破坏性的) 。
概念
现在概念很容易定义, 它们只是约束和公理的结合 。 它们提供了对一个types的语法和语义的抽象要求。
作为一个例子,考虑下面的Ordered
概念:
concept Ordered<Regular T> { requires constraint Less<T>; requires axiom Strict_total_order<less<T>, T>; requires axiom Greater<T>; requires axiom Less_equal<T>; requires axiom Greater_equal<T>; }
首先要注意的是,对于需要Ordered
的模板typesT
,它也必须满足Regular
的要求。 Regular
概念是一个非常基本的要求,types是行为良好的 – 它可以被构build,销毁,复制和比较。
除了这些要求之外, Ordered
要求T
符合一个约束和四个公理:
- 约束:
Ordered
types必须有一个operator<
。 这是静态检查,所以它必须存在。 - 公理:对于
T
型的x
和y
:-
x < y
给出严格的总sorting。 - 当
x
大于y
,y
小于x
,反之亦然。 - 当
x
小于或等于y
,y
不小于x
,反之亦然。 - 当
x
大于或等于y
,y
不大于x
,反之亦然。
-
结合这样的限制和公理给你的概念。 他们定义了用于algorithm的抽象types的语法和语义要求。 algorithm目前不得不假设所使用的types将支持某些操作并expression某些语义。 有了概念,我们就能够确保符合要求。
在最新的概念devise中 ,编译器只会检查模板参数是否满足概念的语法要求。 这些公理没有被检查。 由于公理表示不是静态可评估的语义(或者通常不可能完全检查),因此types的作者必须明确地声明他们的types符合概念的所有要求。 这在之前的devise中被称为概念图,但是已经被移除。
例子
以下是一些概念的例子:
-
Regular
types是可构造的,可破坏的,可复制的,并可以进行比较。 -
Ordered
types支持operator<
,并且具有严格的总sorting和其他sorting语义。 -
可复制types是复制可构造的,可破坏的,如果
x
等于y
且x
被复制,则复制也将等于y
。 -
Iterator
types必须具有相关的typesvalue_type
,reference
,difference_type
和iterator_category
,它们本身必须满足某些概念。 他们还必须支持operator++
并且可以引用。
概念之路
约束是实现C ++完整概念function的第一步。 它们是非常重要的一步,因为它们提供了types的静态可执行的需求,所以我们可以编写更清洁的模板函数和类。 现在我们可以避免std::enable_if
及其元编程的朋友的一些困难和丑陋。
但是,约束build议并没有做很多事情:
-
它不提供概念定义语言。
-
约束不是概念图。 用户不需要特别注明他们的types是否符合某些约束。 他们静态检查使用简单的编译时语言function。
-
模板的实现不受其模板参数的限制。 也就是说,如果你的函数模板对一个约束types的对象做任何事情,那么编译器就无法诊断那个对象。 一个全function的概念提案将能够做到这一点。
约束条款的build议是专门devise的,以便在其上面引入完整的概念build议。 运气好的话,这个过渡应该是一个相当顺利的过程。 概念小组正在寻求为C ++ 14(或不久之后的技术报告)引入约束,而完整的概念可能会在C ++ 17的某个时候出现。
最近(3月12日)概念电话会议纪要和讨论logging第2.3节“精简概念简介”是在同一天发布的: http : //isocpp.org/blog/2013/03 / new-paper-n3576-sg8-concepts-teleconference-minutes-2013-03-12-herb-sutter 。
我的2美分:
-
概念精简提议并不意味着要对模板实现进行“types检查”。 即,Concepts-lite将确保(概念上)在模板实例化站点处的接口兼容性。 从论文引用:“概念精简版是C + +的扩展,允许使用谓词约束模板参数”。 就是这样。 它没有说模板主体将被检查(孤立)与谓词。 这可能意味着当你谈论概念时,没有什么一stream的概念。 如果我没有记错的话,在概念模糊的提案中,提供的types不能less于也不能多于模板的实现 。
-
concepts-lite使用了一些编译器支持的语法技巧来增强constexpr函数。 查找规则没有变化。
-
程序员不需要编写概念图。
-
最后,再次引用“约束提议并不直接涉及语义的规范或使用;它仅针对语法检查”。 这意味着公理不在范围之内(到目前为止)。