【问题标题】:Is it legal for a standard library implementation to specialize a function templated on a concept with a child concept?标准库实现对具有子概念的概念模板化的函数进行专门化是否合法?
【发布时间】:2015-12-09 21:09:14
【问题描述】:

使用 c++11 和 c++14 库概念,c++ 标准库的有效实现可能会创建以概念为模板的函数的专用版本,以利用子概念的附加功能进行优化仅使用基本概念是不可能的,例如std::vectorInputIterator 构造函数和满足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());

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

It a,b;
It::difference_type c = a - b;

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

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


重申一下:c++ 标准库的有效实现是否可以创建以概念为模板的函数的专用版本,以利用子概念的附加功能进行优化,而仅使用基本概念则无法实现?


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

【问题讨论】:

  • 假设你有一些 RandomAccessIterators ab; vector(a, b) 不会模棱两可吗?
  • @immibis 我假设规则与模板的部分特化相同,其中更具体的函数版本会胜出。
  • 成员函数是一个不好的例子,该标准已经允许实现将其签名更改为他们心中的内容,只要对标准中签名的简单调用按规定工作即可。非成员更有趣,但实现总是可以调用重载的__helpers,而不是直接添加重载,而且如果没有 TS 的重载解析支持的概念,他们无论如何都必须这样做。
  • @T.C.但是您实际上不能将构造函数声明为vector(RandomAccessIterator a, RandomAccessIterator b, ...),因为概念实际上并不是语言特性,对吧?你必须做template<class T> vector(T a, T b, ...) 并依赖 SFINAE。
  • @immibis 正确。或者将标签分派到内部助手,这更有可能发生。无论如何,标准都要求“专门化”用于前向或更好迭代器的构造函数。

标签: c++-concepts c++ c++11 language-lawyer c++14


【解决方案1】:

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

所以vector 签名的确切细节可以在 as-if 规则下改变,只要指定的所有构造函数都可以被调用,你得到的行为满足记录的特性,以及任何构造函数参数会无效仍然无效(因为外部代码可以进行 SFINAE 测试以确定给定的参数集是否会构造 std::vector)。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    相关资源
    最近更新 更多