Reputation: 4276
Consider the following program:
int main ()
{
const int e = 10;
for (decltype(e) i{0}; i < e; ++i) {
// do something
}
}
This fails to compile with clang (as well as gcc):
decltype.cpp:5:35: error: read-only variable is not assignable
for (decltype(e) i{0}; i < e; ++i) {
^ ~
Basically, the compiler is assuming that i
must be const, since e
is.
Is there a way I can use decltype
to get the type of e
, but removing the const
specifier?
Upvotes: 58
Views: 18724
Reputation: 141576
A solution not mentioned yet:
for (decltype(+e) i{0}; i < e; ++i)
Prvalues of primitive type have const
stripped; so +e
is a prvalue of type int
and therefore decltype(+e)
is int
.
Upvotes: 10
Reputation: 826
You can also use std::decay
:
#include<type_traits>
...
for (std::decay<decltype(e)>::type i{}; i < e; ++i) {
// do something
}
Upvotes: 16
Reputation: 1604
I prefer range-for. Simulate it is very easy.
#include <iostream>
template< typename T >
struct range_t
{
struct iter
{
T operator * ()const noexcept { return n;}
iter& operator ++()noexcept{ ++n; return *this;}
friend
bool operator != (iter const& lhs, iter const& rhs)noexcept
{ return lhs.n != rhs.n;}
T n;
};
iter begin()const noexcept {return {b};}
iter end() const noexcept{ return {e};}
T b, e;
};
template< typename T > range_t<T> range(T b, T e){ return {b,e}; }
int main()
{
const int e = 10;
for( auto i : range(0,e) )
{
std::cout << i << ' ';
}
return 0;
}
Upvotes: 0
Reputation: 42554
I prefer auto i = decltype(e){0};
for this. It's a bit simpler than using type_traits
, and I feel it more explicitly specifies the intent that you want a variable initialized to a 0 of e
's type.
I've been using Herb's "AAA Style" a lot lately, so it could just be bias on my part.
Upvotes: 60
Reputation: 15278
Use std::remove_const
:
#include<type_traits>
...
for (std::remove_const<decltype(e)>::type i{0}; i < e; ++i)
Upvotes: 55