次のプログラムを検討してください。
int main ()
{
const int e = 10;
for (decltype(e) i{0}; i < e; ++i) {
// do something
}
}
これはclang(およびgcc)でコンパイルできません:
decltype.cpp:5:35: error: read-only variable is not assignable
for (decltype(e) i{0}; i < e; ++i) {
^ ~
基本的に、コンパイラはi
がconstであるため、e
はconstである必要があると想定しています。
decltype
のタイプを取得するためにe
を使用できますが、const
指定子を削除する方法はありますか?
これにはauto i = decltype(e){0};
を使用します。 type_traits
を使用するよりも少し簡単です。また、変数をe
の型の0に初期化する意図をより明示的に指定しているように感じます。
私は最近 Herbの "AAAスタイル" を頻繁に使用しているので、私の部分に偏りがあるかもしれません。
使用する - std::remove_const
:
#include<type_traits>
...
for (std::remove_const<decltype(e)>::type i{0}; i < e; ++i)
#include<type_traits>
...
for (std::decay<decltype(e)>::type i{}; i < e; ++i) {
// do something
}
まだ言及されていない解決策:
_for (decltype(+e) i{0}; i < e; ++i)
_
プリミティブ型の値はconst
が取り除かれています。したがって、_+e
_はint
型のprvalueであるため、decltype(+e)
はint
です。
私はrange-forを好みます。シミュレーションは非常に簡単です。
#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;
}