C+11/14を初めて使ってみたとき、 auto
による型推論は感動を覚えました。
ものすごく長ったらしい型を入力する必要が無くなると分かったときは、 auto
最高!とさえ、思いました。
型推論によって便利になった反面、ソースコードを読み解いたり・読み返すときの可読性は低くなったというトレードオフはありますが、この記事では別の話題を。
auto
の型推論について、私が誤解していたことをここで書こうと思います。
int x = 1; const int cx = x; auto a = cx; auto& b = cx; auto* c = &cx;
このように変数を宣言したとき、変数 a
, b
, c
の型は何になると思いますか?
私の以前の直感は、こうでした
a
:const int
b
:const int&
c
:const int*
が、実際はこれが正しかったんです
a
:int
b
:const int&
c
:const int*
調べてみると、値をコピーするときは、どうやら const
修飾子は無視されるようでした。
更に調べてみると、 auto
の型推論はテンプレートの型推論を利用していて、そのテンプレートの型推論は値渡しのときは const
修飾子を無視するのです。
auto
と const
を使うときは、少しだけ注意しようと思いましたとさ。
おまけ
auto
に推論された型を確認する方法
template<typename T> class TD; int main( int argc, char** argv){ int x = 1; const int cx = x; auto a = cx; auto& b = cx; auto* c = &cx; TD<decltype(x)> xType; TD<decltype(cx)> cxType; TD<decltype(a)> aType; TD<decltype(b)> bType; TD<decltype(c)> cType; return 0; }
コンパイルによるエラーをわざと引き起こし、推論された型を確認することができます。ちなみに、その結果はこちらです。
sample1.cpp: In function 'int main(int, char**)': sample1.cpp:15:20: error: aggregate 'TD<int> xType' has incomplete type and cannot be defined TD<decltype(x)> xType; ^~~~~ sample1.cpp:16:21: error: aggregate 'TD<const int> cxType' has incomplete type and cannot be defined TD<decltype(cx)> cxType; ^~~~~~ sample1.cpp:18:20: error: aggregate 'TD<int> aType' has incomplete type and cannot be defined TD<decltype(a)> aType; ^~~~~ sample1.cpp:19:20: error: aggregate 'TD<const int&> bType' has incomplete type and cannot be defined TD<decltype(b)> bType; ^~~~~ sample1.cpp:20:20: error: aggregate 'TD<const int*> cType' has incomplete type and cannot be defined TD<decltype(c)> cType;