3

The auto type of C++11 is handy, so now one wants a const_auto type, too. For example, supposing std::list<T> a;, if

auto p = a.begin();

has the type std::list<T>::iterator, then one wishes that

const_auto p = a.begin();

had the type std::list<T>::const_iterator. Unfortunately, C++11 does not seem to have heard of const_auto. Therefore, how can one achieve the desired effect with good style, please?

(For information, a related question is asked and answered here.)

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
thb
  • 13,796
  • 3
  • 40
  • 68
  • 1
    Reason why is because auto get the type being assigned to it. const_auto wouldn't make any sense. – Adrian Jun 22 '13 at 02:18
  • 2
    I've used `auto r = some_cv_overloaded_operation(as_const(a));` once or twice, I find it useful when the need arises (writing `as_const` left as an exercise). – Luc Danton Jun 22 '13 at 05:53
  • @Adrian: Of course you are right. Indeed, I understood that when I asked the question. Thank you for explicitly pointing it out, though. – thb Jun 22 '13 at 12:58
  • @LucDanton: Your comment makes a good answer. If you added it as an answer, then naturally I would upvote it. – thb Jun 22 '13 at 13:01

3 Answers3

13

C++11 does allow you to write

const auto p = a.begin();

However, this doesn't do what you want. This makes a regular iterator to non-constant data whose value cannot be changed.

The type of the right-hand side a.begin()is determined by the type of a, and not by anything on the left-hand side. If a is non-const, then the non-const version of a.begin() will be called. So, you could cast a to a const& and then use it, or you could make a constant reference to a and use that:

const auto& b = a;
auto p = b.begin();

However, a simpler approach would be to use the newly introduced .cbegin() and .cend():

auto p = a.cbegin();
BenRI
  • 724
  • 6
  • 17
  • Thank you. I had not known that. Can one moreover do likewise with pointers? That is, if iterators are not involved, but only old-fashioned pointers, then can one somehow use `auto` to get a type like `const T *`? – thb Jun 22 '13 at 01:42
  • Can't do it with pointers since there is no way to determine the **'end'**, but you can do it with arrays. – Adrian Jun 22 '13 at 02:40
  • 1
    Also, if I remember correctly, this will be possible in C++14: `auto p = cbegin(a);` which does the same but is more generic as it works too if 'a' is a raw array. – Klaim Jun 22 '13 at 10:42
3

I often find it useful to turn instances into the const version of their type, but I find using const_cast to be vulgar for this purpose (reserve that for removing const, and now searching for it finds dangerous code), and it is overly verbose (repeating the full type? Gah!)

Hence this snippet:

template<typename T>
T const& as_const( T& t ) { return t; }

which you'd then use to solve your problem as follows:

auto p = as_const(a).begin();

which I believe is pretty self documenting.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
2

There are function templates for STL containers and C arrays in C++11. See std::begin() and std::end(). Unfortunately, there is no equivalent std::cbegin() or std::cend() for some reason.

You can use these functions to do what you want though:

template<class T, size_t N>
T const * cbegin(T(&a)[N])
{
    return &a[0];
}

template<class T, size_t N>
T const * cend(T(&a)[N])
{
    return &a[N];
}

template<class T>
typename T::const_iterator cbegin(T const & container)
{
    return container.cbegin();
}

template<class T>
typename T::const_iterator cend(T const & container)
{
    return container.cend();
}

The last two can also be declared as:

template<class T>
auto cbegin(T const & container) -> decltype(container.cbegin())
{
    return container.cbegin();
}

template<class T>
auto cend(T const & container) -> decltype(container.cend())
{
    return container.cend();
}

From there you can do this:

char x[] = "ab";

auto b = cbegin(x);
auto e = cend(x);
Adrian
  • 10,246
  • 4
  • 44
  • 110
  • I think these are to be in [added](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3688.html#2128) to the standard. I believe someone hacking libstdc++ is working on it. – emsr Jun 22 '13 at 22:49