【问题标题】:Does the C++ Standard Library prohibit non-standard iterator categories?C++ 标准库是否禁止非标准迭代器类别?
【发布时间】:2014-11-13 02:43:21
【问题描述】:

以下创建用户定义的迭代器类别标签的程序被clang(使用-stdlib=libc++)拒绝,但不会被其他编译器和标准库实现拒绝:

#include <iterator>

struct my_iterator_tag {};

struct my_iterator : std::iterator<my_iterator_tag, int> {};

int main()
{
  std::iterator_traits<my_iterator>::value_type x;
  return 0;
}

我不清楚 C++ 标准是否禁止使用具有非标准迭代器类别的迭代器类型实例化 std::iterator_traits

这个程序非法吗?

clang 的输出(使用 libc++ 时)如下:

$ clang -stdlib=libc++ test.cpp 
test.cpp:9:38: error: no type named 'value_type' in 'std::__1::iterator_traits<my_iterator>'
  std::iterator_traits<my_iterator>::value_type x;
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
1 error generated.

【问题讨论】:

    标签: c++ iterator


    【解决方案1】:

    std::iterator模板定义如下:

    template<class Category, class T, class Distance = ptrdiff_t,
        class Pointer = T*, class Reference = T&> struct iterator {
        typedef T value_type;
        typedef Distance difference_type;
        typedef Pointer pointer;
        typedef Reference reference;
        typedef Category iterator_category;
      };
    }
    

    我看不出你的声明有什么问题:

    struct my_iterator : std::iterator<my_iterator_tag, int> {};
    

    所以,粗略地说,你最终定义了:

    struct my_iterator {
    
        // ...
    
        typedef Category my_iterator_tag;
    
        // ...
    };
    

    看不出有什么问题。这是一个有效的声明。

    现在,我们来看看iterator_traits的定义:

    template<class Iterator> struct iterator_traits {
       typedef typename Iterator::difference_type difference_type;
       typedef typename Iterator::value_type value_type;
       typedef typename Iterator::pointer pointer;
       typedef typename Iterator::reference reference;
       typedef typename Iterator::iterator_category iterator_category;
    };
    

    将此模板应用于my_iteratorIterator,我在这里也没有发现任何技术上的错误。这些模板的上述定义直接来自标准。因此,就 C++11 标准中这些模板的实际严格、文字声明而言,我认为这些声明没有任何问题。

    当然,C++ 标准定义了五个标准迭代器类别,因此就 C++ 库的其余部分而言,有必要进一步分析。我想像迭代器适配器这样的各种东西可能是未定义的行为,除了五个标准迭代器类别之外的任何东西。

    粗略地看一下,我找不到任何明确指出使用 std::iteratorstd::iterator_traits 的五个预定义标签以外的任何东西是未定义行为的内容,因此仅在这个有限的示例中,我想说这在技术上是有效的,尽管它的价值值得怀疑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-17
      • 2012-03-05
      • 1970-01-01
      • 2015-05-11
      • 2011-05-16
      • 1970-01-01
      相关资源
      最近更新 更多