【问题标题】:Can I rely on initializer_list::const_iterator being a plain pointer?我可以依靠 initializer_list::const_iterator 作为普通指针吗?
【发布时间】:2017-06-13 20:45:54
【问题描述】:

This question 表示std::initializer_list<int>::const_iterator 类型只是一个普通的int const* 指针,但this answer 中引用的标准措辞(针对同一个问题)听起来更像是建议而不是保证.

在我的代码中,问题发生如下:我有一个函数处理 initializer_list 的子范围,而在不同的情况下,我重用了传递单个元素的便捷函数中的代码(作为单元素范围):

void doStuff(int const* begin, int const* end)
{ ... do stuff ... }

  // main use; in the real code, 'init' is a parameter of a function
  std::initializer_list<int> init({1, 2, 3, 4, 5});
  doStuff(init.begin() + 1, init.end());

  // alternative use of doStuff, relies on the pointer assumption
  int x = 6;
  doStuff(&x, (&x) + 1);
}

这种构造依赖于迭代器确实是指针这一事实。它至少适用于我的 clang++ 3.9 编译器。我可以依靠它来始终工作吗,即指针假设是否可移植?保证便携?还是我应该将doStuff 的参数类型更改为模板参数,以确保安全?

template <typename Iterator>
void doStuff(Iterator begin, Iterator end)
{ ... do stuff ... }

【问题讨论】:

  • 来自 cppreference,它是 seems you can。也就是要么可以,要么cppreference错
  • @Justin 好点,但我无法判断来源。是他们对标准的阅读,还是这个网站由标准委员会维护?我没有找到确切的来源。
  • @tglas 您可以查看当前标准的草案(可在 isocpp.org 获得)并参阅 §21.9.1。
  • 迭代器是迭代器。假设它们是指针或其他特定类型是错误的。一个不应该在可移植代码中做出这样的假设(保证与否)。只是我的拙见。

标签: c++ pointers iterator initializer-list


【解决方案1】:

是的,您可以信赖它,C++14 的 18.9 为我们在 class initializer_list 内部提供了定义:

typedef const E* iterator; typedef const E* const_iterator;

C++ 中的其他类型是不同的——例如std::vector,其中迭代器是实现定义的,有些实现使用原始指针作为迭代器,有些使用类。

【讨论】:

  • 哇,真快。谢谢!
  • 今天早上我还是切换到了 C++14,所以这听起来是确定的答案。
【解决方案2】:

标准的第 18.9 节给出了&lt;initializer_list&gt; 标头的概要,如下所示:

namespace std {
  template<class E> class initializer_list {
  public:
    typedef E value_type;
    typedef const E& reference;
    typedef const E& const_reference;
    typedef size_t size_type;
    typedef const E* iterator;
    typedef const E* const_iterator;
    constexpr initializer_list() noexcept;
    constexpr size_t size() const noexcept; // number of elements
    constexpr const E* begin() const noexcept; // first element
    constexpr const E* end() const noexcept; // one past the last element
  };
  // 18.9.3 initializer list range access
  template<class E> constexpr const E* begin(initializer_list<E> il) noexcept;
  template<class E> constexpr const E* end(initializer_list<E> il) noexcept;
}

此外,initializer_list 上的 begin()end() 函数保证返回 const E*,正如我们从 18.9.2 中看到的那样。

所以是的,您可以信赖它。

【讨论】:

  • 请注意,并非所有的概要都是规范的。
猜你喜欢
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 1970-01-01
  • 2016-01-10
  • 2021-09-25
  • 1970-01-01
相关资源
最近更新 更多