c++ - std::iterator_traits libstdc++ 和 libc++ 之间的分歧

标签 c++ language-lawyer libc++ compiler-bug iterator-traits

给定:

struct Iter {
    using value_type = int;
    using difference_type = int;
    using reference = int;
    using pointer = int;
    using iterator_category = int;
};

以下代码适用于 libstc++,但无法针对 libc++ 5.0.0 进行编译:

#include <iterator>
#include <type_traits>
static_assert(
    std::is_same<
        std::iterator_traits<Iter>::iterator_category,
        Iter::iterator_category
    >::value, "");

出现错误:

error: no member named 'iterator_category' in 'std::__1::iterator_traits<Iter>' std::is_same<std::iterator_traits<Iter>::iterator_category, Iter::iterator_category>::value, "");

如果Iter::iterator_category,则静态断言成功是标准输入类别之一,例如std::input_iterator_tag .

恕我直言,它不应该失败,因为 C++ 草案在 [iterator.traits]#2 中声明:

If Iterator has valid ([temp.deduct]) member types difference_­type, value_­type, pointer, reference, and iterator_­category, iterator_­traits<Iterator> shall have the following as publicly accessible members:

using difference_type   = typename Iterator::difference_type;
using value_type        = typename Iterator::value_type;
using pointer           = typename Iterator::pointer;
using reference         = typename Iterator::reference;
using iterator_category = typename Iterator::iterator_category;

Otherwise, iterator_­traits<Iterator> shall have no members by any of the above names.

谁能解释一下这是否是一个实现错误,或者为什么我的期望是错误的?

最佳答案

我们也有,在[std.iterator.tags] :

It is often desirable for a function template specialization to find out what is the most specific category of its iterator argument, so that the function can select the most efficient algorithm at compile time. To facilitate this, the library introduces category tag classes which are used as compile time tags for algorithm selection. They are: input_­iterator_­tag, output_­iterator_­tag, forward_­iterator_­tag, bidirectional_­iterator_­tag and random_­acces_­iterator_­tag. For every iterator of type Iterator, iterator_­traits<Iterator>​::​iterator_­category shall be defined to be the most specific category tag that describes the iterator's behavior.

namespace std {
  struct input_iterator_tag { };
  struct output_iterator_tag { };
  struct forward_iterator_tag: public input_iterator_tag { };
  struct bidirectional_iterator_tag: public forward_iterator_tag { };
  struct random_access_iterator_tag: public bidirectional_iterator_tag { };
}

int不是这些标签之一,所以 iterator_traits<Iter>::iterator_category不能还给你int .我建议拥有一个无效的迭代器类别只是违反了 iterator_traits 的前提条件。 - 这并不一定意味着库一定会失败,但也不意味着失败是库错误。

但是,这些先决条件在 [iterators] 中没有像在库部分的其他部分中那样明确说明。所以我倾向于建议这两个库都是正确的,但是 libc++ 不在 iterator_traits<Iter> 中定义任何成员别名的方法。可能更好。

关于c++ - std::iterator_traits libstdc++ 和 libc++ 之间的分歧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47513930/

相关文章:

基类中的 C++ 异常处理

c++ - 如何使用 Boost 库更改文件权限?

C++ 模板类

c++11 - 这个简单的结构应该有一个隐式的移动构造函数吗?

linux - 我应该使用 libc++ 还是 libstdc++?

c++ - 视觉 C++/工作室 : Application configuration incorrect?

c++ - 在不同源文件中声明的相同名称类没有编译器/链接器错误

c++ - 在没有 std::launder 的情况下将 std::aligned_storage* 重新解释为 T* 是否违反严格别名规则?

c++ - 如何让 clang 搜索 gcc 的头文件?

c++ - clang 的 libc++ 产品准备好了吗?