(序言:我是C ++ 0x游戏的后续追随者,最近有关从C ++ 0x标准中删除概念的争议促使我更多地了解它们。虽然我理解我的所有问题都是完全假设的 - 只要概念在未来一段时间内不是有效的C ++代码,如果有的话 - 我仍然有兴趣学习更多关于概念的知识,特别是考虑到它会如何帮助我更充分地了解最近的决定背后的优点以及随之而来的争议。
在阅读了一些关于概念的介绍性材料之后,就像C ++ 0x(直到最近)提出的那样,我在思考一些语法问题时遇到了麻烦。不用多说,这是我的问题:
1)支持特定派生概念的类型(隐式地,通过auto关键字,还是显式地通过concept_maps)是否也需要独立支持基本概念?换句话说,从另一个概念中导出概念的行为(例如concept B<typename T> : A<T>
)是否隐含地包含“隐形”需求声明(在B中,requires A<T>;
)?混淆源于维基百科关于概念的页面:
就像在类继承中那样,类型 符合派生的要求 概念也符合要求 基本概念。
这似乎说一种类型只需要满足派生概念的要求,而不一定是基本概念的要求,这对我来说毫无意义。我知道维基百科远非一个明确的来源;以上描述只是一个不好的选择?
2)列出类型名称的概念可以是“自动”吗?如果是这样,编译器将如何自动映射这些类型名称?如果没有,是否有任何其他场合在概念上使用'auto'无效?
澄清一下,请考虑以下假设代码:
template<typename Type>
class Dummy {};
class Dummy2 { public: typedef int Type; };
auto concept SomeType<typename T>
{
typename Type;
}
template<typename T> requires SomeType<T>
void function(T t)
{}
int main()
{
function(Dummy<int>()); //would this match SomeType?
function(Dummy2()); //how about this?
return 0;
}
这些类中的任何一个都会匹配SomeType吗?或者是涉及类型名称的概念所必需的concept_map?
3)最后,我很难理解允许定义哪些公理。例如,我是否可以定义一个逻辑上不一致的公理,例如
concept SomeConcept<typename T>
{
T operator*(T&, int);
axiom Inconsistency(T a)
{
a * 1 == a * 2;
}
}
那会怎么做?这甚至有效吗?
我感谢这是一个很长的问题,所以我提前感谢你。
答案 0 :(得分:10)
我使用了最新的C ++ 0x草案N2914(其中仍有概念措辞)作为以下答案的参考。
1)概念就像接口一样。如果您的类型支持一个概念,它也应该支持所有“基础”概念。你引用的维基百科声明从类型客户的角度来看是有意义的 - 如果他知道T
满足概念Derived<T>
,那么他也知道它满足概念Base<T>
。从类型作者的角度来看,这自然意味着两者都必须得到实施。见14.10.3 / 2。
2)是的,typename
成员的概念可以是auto
。如果这些成员用于相同概念中的功能成员的定义,则可以自动推断出这些成员。例如,可以推导出value_type
for iterator作为其operator*
的返回类型。但是,如果类型成员未在任何地方使用,则不会推导出它,因此不会隐式定义。在您的示例中,无法为SomeType<T>::Type
或Dummy
推断Dummy1
,因为Type
未被概念的其他成员使用,因此两个类都不会映射概念(实际上,没有类可以自动映射到它)。见14.10.1.2/11和14.10.2.2/4。
3)公理是规范的一个弱点,它们不断更新以产生一些(更多)意义。就在概念被从草案中拉出来之前,有一个paper发生了很大变化 - 阅读它并看看它是否对你更有意义,或者你仍然对它有疑问。
对于您的具体示例(考虑语法差异),这意味着允许编译器将表达式(a*1)
视为与(a*2)
相同,以用于“as-if” “语言规则(即编译器允许进行它想要的任何优化,只要结果表现为,好像没有)。但是,编译器不需要以任何方式验证公理的正确性(因此它们被称为公理!) - 它只是将它们视为它们的原因。