它想要进行什么样的邪恶魔法!?!
我在听与Herb Sutter进行的问答环节时,有一个问题是关于概念的。Herb提到它会使编译器变慢(即使源代码没有改变),而且这个部分比模板的部分显着更大。
为什么会这样?我在哪里可以找到关于概念的文档?
它想要进行什么样的邪恶魔法!?!
我在听与Herb Sutter进行的问答环节时,有一个问题是关于概念的。Herb提到它会使编译器变慢(即使源代码没有改变),而且这个部分比模板的部分显着更大。
为什么会这样?我在哪里可以找到关于概念的文档?
注意:以下答案(以及它回答的问题)涉及旧版C++0x的概念,与添加到C++20中的该功能版本没有多少关系。
首先,Herb并没有说概念本身会使编译变慢。他说将概念应用于C++标准库会使使用C++标准库的任何代码编译变慢。
这是由于以下几个原因:
1:限定模板需要编译时间。
当您像这样声明一个类:
template<typename T> class Foo {...};
编译器只是简单地解析Foo,做的事情非常少。即使进行两阶段查找,编译器在编译类Foo时也只是做了很少的工作。当然,它会将其存储以备后用,但初始遍历相对较快。
当您使用概念约束模板时:
template<ConceptName C> class Foo {...};
编译器必须执行某些操作。它必须事先检查类型C的每个使用是否符合概念ConceptName。这是编译器本可以推迟到实例化时处理的额外工作。
你拥有越多的概念检查,你就需要花费更多的编译时间来验证类型是否与概念匹配。
2:标准C++库使用了很多概念。
看一下迭代器概念的数量:输入、输出、前向、双向、顺序、连续。委员会正在考虑将它们分解成更多的部分。许多算法将具有多个版本,适用于不同的迭代器概念。
这还不包括范围概念(除输出迭代器概念外,每种迭代器概念都有一个),std::string的字符概念以及各种其他类型的概念。所有这些都必须被编译和检查。
由于这个问题相当陈旧(来自2011年),而且在撰写本文时(2020年)已经发布了概念,因此我想澄清一些事情,以免误导人们或阻止他们使用概念。
过去被认为的概念和现在发布的概念是完全不同的。C++20中发布的概念也被称为“概念lite”,因为它们包含比概念最初设计时减少的功能。那么一开始的概念失去了什么呢?
主要区别在于,概念的首要设计目的旨在检查模板的使用正确性和定义正确性。例如,假设您有一个具有类型Animal
的模板,需要具有成员函数make_sound
。您可以像下面这样想象一个受约束的函数模板:
template <typename Animal>
requires requires(Animal& x){
x.make_sound();
}
int animal_tricks(Animal& x) {
x.make_sound();
x.do_trick();
}
animal_tricks
是不正确的,因为我们使用了一个do_trick
成员函数,它不是所需表达式的一部分。然而,通过C++20概念lite,这种概念定义是合法的。在概念lite世界中,编译器不会检查animal_tricks
函数模板的正确性,开发人员需要正确地指定类型的要求。你可能会在ConceptsGCC网站上找到有用的资源。这是他们正在构建的编译器(从GCC分支出来),以查看该概念是否可行。
我想开销来自于必须对各种语言结构执行彻底、普遍和递归的有效性检查,而且考虑到你可以指定相当丰富的约束条件,检查这些条件可能会变得非常昂贵。
有点像异常规范的噩梦版本!