我想知道C ++完整概念提议和模板约束(例如,Dlang中出现的约束或C ++ 1y的新的 Lites -lite提议)之间的语义区别是什么。
模板约束不能完成的成熟概念有什么功能?
我想知道C ++完整概念提议和模板约束(例如,Dlang中出现的约束或C ++ 1y的新的 Lites -lite提议)之间的语义区别是什么。
模板约束不能完成的成熟概念有什么功能?
Answers:
以下信息已过期。需要根据最新的Concepts Lite草稿进行更新。
约束建议的第3节在合理的深度中对此进行了介绍。
概念提案已经搁浅了片刻,希望可以充实并在更短的时间范围内实现约束(即,lites-lite),目前至少针对C ++ 14。约束提议旨在充当向概念的更高定义的平稳过渡。约束是概念建议的一部分,并且是其定义中的必要组成部分。
在C ++概念库的设计中,Sutton和Stroustrup考虑以下关系:
概念=约束+公理
为了快速总结其含义:
因此,如果将公理(语义属性)添加到约束(句法属性),则会得到概念。
精简概念提案只给我们带来了第一部分约束,但这是迈向成熟概念的重要而必要的步骤。
约束都与语法有关。它们为我们提供了一种在编译时静态识别类型属性的方法,以便我们可以基于其语法属性来限制用作模板参数的类型。在当前的约束建议中,它们使用逻辑连接词如&&
和表示为命题演算的子集||
。
让我们看一下约束的作用:
template <typename Cont>
requires Sortable<Cont>()
void sort(Cont& container);
在这里,我们定义了一个名为的功能模板sort
。新增加的是require子句。require子句对该函数的模板参数给出了一些约束。特别是,此约束表明类型Cont
必须是Sortable
类型。一件整洁的事情是,它可以用更简洁的形式写成:
template <Sortable Cont>
void sort(Cont& container);
现在,如果您尝试将不考虑的任何内容传递Sortable
给该函数,您将得到一个不错的错误,该错误立即告诉您推断出的类型T
不是Sortable
类型。如果您在C ++ 11中完成了此操作,则函数内部将引发一些可怕的错误sort
,这对任何人都没有意义。
约束谓词与类型特征非常相似。他们采用一些模板参数类型,并提供一些有关它的信息。约束试图回答以下有关类型的问题:
但是,约束并不是要替换类型特征。相反,他们将携手并进。现在可以根据概念定义某些类型特征,而根据类型特征可以定义某些概念。
因此,约束的重要之处在于它们不必关心语义。约束的一些很好的例子是:
Equality_comparable<T>
:检查类型是否==
具有相同类型的两个操作数。
Equality_comparable<T,U>
:检查==
给定类型的操作数是否带有左右操作数
Arithmetic<T>
:检查类型是否为算术类型。
Floating_point<T>
:检查类型是否为浮点类型。
Input_iterator<T>
:检查类型是否支持输入迭代器必须支持的语法操作。
Same<T,U>
:检查给定类型是否相同。
现在,我们进入了除了轻量级概念提案之外的所有内容。这比未来本身更具未来性。从这里到现在的一切都可能会发生很大变化。
公理都是关于语义的。它们指定关系,不变式,复杂性保证和其他类似的东西。让我们来看一个例子。
尽管Equality_comparable<T,U>
约束会告诉你有一个operator==
需要类型T
和的约束U
,但是它并没有告诉你该操作的含义。为此,我们将拥有公理Equivalence_relation
。该公理说,将这两种类型的对象与operator==
给定进行比较时true
,这些对象是等效的。这似乎是多余的,但肯定不是。您可以轻松定义一个operator==
行为类似于operator<
。您这样做很邪恶,但是可以。
另一个例子是Greater
公理。T
可以将两个类型的对象与>
和<
运算符进行比较很好,但是它们是什么意思呢?该Greater
公理说,当且仅当x
是大于y
,则y
是小于x
。拟议的规范,例如一个公理,看起来像:
template<typename T>
axiom Greater(T x, T y) {
(x>y) == (y<x);
}
因此,公理回答以下类型的问题:
也就是说,他们完全关心类型的语义以及对这些类型的操作。这些东西不能被静态检查。如果需要对此进行检查,则类型必须以某种方式声明其遵循这些语义。
以下是一些公理的常见示例:
Equivalence_relation
:如果两个对象比较==
,则它们是等效的。
Greater
:无论何时x > y
,然后y < x
。
Less_equal
:无论何时x <= y
,然后!(y < x)
。
Copy_equality
:对于x
和y
类型T
:如果x == y
,则是通过复制构造创建的T{x} == y
并且具有相同类型的新对象,并且该对象仍然x == y
是非破坏性的。
现在,概念很容易定义。它们仅仅是约束和公理的组合。它们提供了对类型的语法和语义的抽象要求。
例如,请考虑以下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>;
}
首先请注意,要使模板类型T
为Ordered
,它还必须满足Regular
概念的要求。该Regular
概念是类型良好的非常基本的要求-可以对其进行构造,销毁,复制和比较。
除了这些要求之外,还Ordered
需要T
满足一个约束和四个公理:
Ordered
类型必须具有operator<
。这是静态检查的,因此它必须存在。x
和y
类型T
:
x < y
给出严格的整体订购。x
大于时y
,y
小于x
,反之亦然。x
小于或等于时y
,y
不小于x
,反之亦然。x
大于或等于时y
,y
不大于x
,反之亦然。像这样将约束和公理相结合,可以为您提供概念。它们定义了与算法一起使用的抽象类型的句法和语义要求。当前,算法必须假定所使用的类型将支持某些操作并表达某些语义。通过概念,我们将能够确保满足要求。
在最新的概念设计中,编译器将仅检查模板参数是否满足概念的句法要求。公理未经检查。由于公理表示无法静态评估的语义(或通常无法完全检查的语义),因此类型的作者必须明确声明其类型符合概念的所有要求。在以前的设计中,这被称为概念映射,但是此后已被删除。
以下是一些概念示例:
Regular
类型是可构造的,可破坏的,可复制的,并且可以进行比较。
Ordered
类型support operator<
,并具有严格的总排序和其他排序语义。
Copyable
类型是可复制构造的,可破坏构造的,并且如果x
等于y
且x
被复制,则副本还将比较等于y
。
Iterator
类型必须具有相关的类型value_type
,reference
,difference_type
,和iterator_category
它本身必须符合一定的概念。它们还必须支持operator++
并且可以取消引用。
约束是迈向C ++完整概念功能的第一步。它们是非常重要的一步,因为它们提供了类型的静态可执行要求,以便我们可以编写更加简洁的模板函数和类。现在我们可以避免std::enable_if
它及其元编程朋友的某些困难和丑陋。
但是,约束提议在很多方面没有做:
它不提供概念定义语言。
约束不是概念图。用户不需要特定注释他们的类型来满足某些约束。使用简单的编译时语言功能对它们进行静态检查。
模板的实现不受模板参数约束的约束。也就是说,如果函数模板对约束类型的对象执行了不应执行的任何操作,则编译器将无法对其进行诊断。一个功能全面的概念提案将能够做到这一点。
约束提议是专门设计的,因此可以在其之上引入完整的概念提议。运气好的话,这种过渡应该是相当顺利的。概念小组正在寻求引入C ++ 14的约束(或随后不久的技术报告中),而完整的概念可能会在C ++ 17左右的某个时候出现。
另请参阅最近(3月12日)概念电信会议记录和讨论记录的第2.3节中的“关于概念lite的'精简内容',当天发布在此处:http : //isocpp.org/blog/2013/03 / new-paper-n3576-sg8-concepts-teleconference-minutes-2013-03-12-herb-sutter。
我的2美分:
Lite-Lite建议并不意味着对模板实现进行“类型检查” 。即,Concepts-lite将确保(在名义上)模板实例化站点的接口兼容性。引用本文的内容:“ concepts lite是C ++的扩展,允许使用谓词来约束模板参数”。就是这样。它并没有说将针对谓词检查模板主体(单独)。这可能意味着当您谈论轻度概念时,没有一流的原型概念。如果我没记错的话,在概念繁杂的提案中,原型是提供不多也不再满足实现的类型模板而。
精简版Concepts使用美化的constexpr函数以及编译器支持的一些语法技巧。查找规则没有变化。
不需要程序员编写概念图。
最后,再次引用“约束建议不直接解决语义的指定或使用;它仅针对检查语法。” 这将意味着公理不在范围内(到目前为止)。