数学やプログラミングの備忘録

数理最適化, Python, C++をメインに紹介するブログ。

MENU

C+11/14: autoの型推論とconst修飾子

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 修飾子を無視するのです。

autoconst を使うときは、少しだけ注意しようと思いましたとさ。

おまけ

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;