Using decltype to get an expression's type, without the const

C++C++11Decltype

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

Use std::remove_const:

#include<type_traits>
...
for (std::remove_const<decltype(e)>::type i{0}; i < e; ++i)

Solution 3 - C++

You can also use std::decay:

#include<type_traits>
...
for (std::decay<decltype(e)>::type i{}; i < e; ++i) {
  // do something
}

Solution 4 - C++

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.

Solution 5 - C++

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJim GarrisonView Question on Stackoverflow
Solution 1 - C++CaseyView Answer on Stackoverflow
Solution 2 - C++zchView Answer on Stackoverflow
Solution 3 - C++klausView Answer on Stackoverflow
Solution 4 - C++M.MView Answer on Stackoverflow
Solution 5 - C++Khurshid NormuradovView Answer on Stackoverflow