简体   繁体   中英

Can I rely on initializer_list::const_iterator being a plain pointer?

This question indicates that std::initializer_list<int>::const_iterator type is just a plain int const* pointer, but the wording of the standard as cited in this answer (to the same question) sounds more like a suggestion than like a guarantee to me.

In my code, the problem occurs as follows: I have a function processing a sub-range of an initializer_list , and in a different situation I reuse the code from a convenience function passing a single element (as a single-element range):

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);
}

This construction relies on the fact that iterators are indeed pointers. It works at least with my clang++ 3.9 compiler. Can I rely on this to always work, ie, is the pointer assumption portable? guaranteed to be portable? Or should I rather change the argument type of doStuff into a template parameter, to be on the safe side?

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

Yes, you can rely on it, 18.9 from C++14 gives us inside class initializer_list the definitions:

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

Other types in C++ are different -- for example std::vector , where the iterator is implementation defined, and some implementations use a raw pointer as an iterator, and some use a class.

Section 18.9 of the standard gives a synopsis of the <initializer_list> header as follows:

 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; } 

Furthermore, the begin() and end() functions on an initializer_list are guaranteed to return a const E* , as we can see from 18.9.2.

So yes, you can rely on it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM