对于标准库实现来说,专门化一个带有子概念的概念上的函数是否合法?

jag*_*ire 7 c++ language-lawyer c++11 c++14

使用c ++ 11和c ++ 14库概念,c ++标准库的有效实现可以创建一个概念上模板化的函数的专用版本,以利用子概念的附加功能进行优化,而不是可能只有基本概念,例如InputIterator构造函数std::vector和满足要求的迭代器RandomAccessIterator

// specified by standard
vector(InputIt begin, InputIt end, const Allocator& alloc = Allocator());
// is this specialization allowed in an implementation if it provides the same functionality?
vector(RandomAccessIt begin, RandomAccessIt end, const Allocator& alloc = Allocator());
Run Code Online (Sandbox Code Playgroud)

在这里,InputIt是一种满足InputIterator概念要求的类型,并RandomAccessIt满足要求RandomAccessIterator.值得注意的是,这个概念缺乏找到两个迭代器之间差异的要求,而它的曾孙概念RandomAccessIterator 确实需要

It a,b;
It::difference_type c = a - b;
Run Code Online (Sandbox Code Playgroud)

有效.找到两个迭代器之间的差异将是InputIterator构造函数的帮助,std::vector在这种情况下RandomAccessIterator也是由提供的迭代器实现的概念,因为它允许实现预先分配最终向量所需的空间,而不是调整它的大小施工期间多次.

我可以看到它是有效的,因为标准偶尔使用as-if规则,例如继承层次结构中的虚函数的协变返回类型.但是,情况之间存在相当明显的差异,因此我也可以看到协变返回类型背后的逻辑可能不一定转移到这种情况.


重申一下:c ++标准库的有效实现是否可以创建一个概念上模板化的功能的专用版本,以利用子概念的附加功能进行优化,而单独使用基本概念是不可能的?


注意:我没有使用标记这个问题因为据我所知,该标签适用于Concepts-Lite和Concepts TS,这个问题是关于c ++ 11和c ++ 14中的库概念.

Yak*_*ont 2

在 C++ 中,无法从外部确定您使用给定签名调用了哪个构造函数。

因此,vector只要可以调用所有指定的构造函数,您获得的行为满足记录的功能,并且任何无效的构造函数参数仍然无效,签名的确切细节就可以根据 as-if 规则进行变化(因为外部代码可以进行 SFINAE 测试以确定给定的参数集是否可以构造std::vector)。

正如OP和评论所指出的,许多标准库实现只是使用标签调度来转发到更高效、更专业的版本。

有趣的是构造函数上下文之外的答案,您可以在其中检测具有特定签名(而不仅仅是兼容性)的函数,并且可以区分不同的函数。我不知道这里的答案,但我的(未经验证的)印象是,与标准中描述的确切签名不匹配的函数有时实际上会出现在std库中。