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.