C++11の新機能として簡単に使用できるのが型推論です。 従来のC++では変数等を作成する場合、型(char、int、double、...etc)を明示的に指定する必要があります。 そこでC++11では型推論という機能があります。 1: auto a = 1; //aはint型 2: auto b = 1 + 1.0; //bはdouble型 3: decltype(a) c; //cはint型 4: decltype(a + b) d; //dはdouble型 autoは変数が受け取る値に応じて型を決定します。なので、宣言した時に必ず初期化しなければいけません。 これだけだと、型に対して柔軟に対応出来るようになっただけの用に思えるかもしれませんので、実際に使用する場面について説明します。 STLのvectorの配列の中身をiteratorを使用して見る際、従来のやり方の場合 1: #include <iostream> 2: #include <vector> 3: 4: using namespace std; 5: 6: int main() 7: { 8: vector<int> vec; 9: 10: for (int i = 0; i < 10; i++) 11: { 12: vec.push_back(i); 13: } 14: 15: vector<int>::iterator it = vec.begin(); 16: 17: while (it != vec.end()) 18: { 19: cout << *it << endl; 20: 21: it++; 22: } 23: 24: return 0; 25: } のようになると思います。この時、15行目の vector<int>::iterator it = vec.begin(); がイテレータにvecの先頭アドレスを代入しているのですが、 vector<int>::iterator このイテレータは、int型を格納するvectorにしか使用できません。また、今回の場合int型なので短いですが、型の種類によっては長くなり一行で書いた際に可読性が下がる問題があります。 auto it = vec.begin(); になり、非常にスマートになるのが分かります。また、同じようにイテレータを使うもの(list、map、...etc)に関しては全てこの書き方で済みます。 1: #include <iostream> 2: #include <vector> 3: 4: using namespace std; 5: 6: int main() 7: { 8: vector<int> vec; 9: 10: for (int i = 0; i < 10; i++) 11: { 12: vec.push_back(i); 13: } 14: 15: auto it = vec.begin();//イテレータを書くのが楽に! 16: 17: while (it != vec.end()) 18: { 19: cout << *it << endl; 20: 21: it++; 22: } 23: 24: return 0; 25: } になります。 次に、decltypeを使用する例を説明します。プログラムによっては 1: #include <vector> 2: 3: using namespace std; 4: 5: int main() 6: { 7: auto a = func();//funcで複雑な型の何かが返される 8: 9: vector</*変数aの型を格納したい!*/> vec; 10: 11: return 0; 12: } のように、vector等で関数から受け取った値の型を指定したい場合があります。しかし、autoはあくまでも受け取った際の型を推論してくれるだけなので、9行目を vector<auto> vec; や vector<a> vec; というように書くことは出来ません。そこでdecltypeを使用することによって実現することが出来ます。 vector<decltype(a)> vec; decltypeはこのようにテンプレートを使用したものに対して型を指定する時に使用することができます。 1: #include <vector> 2: 3: using namespace std; 4: 5: int main() 6: { 7: auto a = func();//funcで複雑な型の何かが返される 8: 9: vector<decltype(a)> vec; 10: 11: return 0; 12: } のようになります。 最後にautoとdecltypeを複合して、戻り値の型が変化する関数の書き方を説明します。 1: #include <iostream> 2: 3: using namespace std; 4: 5: template<typename T1, typename T2> 6: T1 func(T1 a, T2 b) 7: { 8: return a + b; 9: } 10 11: int main() 12: { 13: cout << func(1, 1.5) << endl;//2が出力される 14: 15: cout << func(1.5, 1) << endl;//2.5が出力される 16: 17: return 0; 18: } どちらか一方の型を返すため、使用する側が注意する必要があります。(1.0にすればよくね?っていうツッコミした奴、屋上) 1: #include <iostream> 2: 3: using namespace std; 4: 5: template<typename T1, typename T2> 6: auto func(T1 a, T2 b) -> decltype(a + b) 7: { 8: return a + b; 9: } 10 11: int main() 12: { 13: cout << func(1, 1.5) << endl;//2.5が出力される 14: 15: cout << func(1.5, 1) << endl;//2.5が出力される 16: 17: return 0; 18: } と書く(6行目に注目)ことによって、どちらがint型であっても、戻り値をdoubleにすることが出来ます。 //C++14の場合 template<typename T1, typename T2> auto func(T1 a, T2 b) { return a + b; } 今回説明したauto、decltypeは複雑な機能ではないのですぐに使用できるようになると思います。(とりあえずイテレータにautoはオススメ) 以上で型推論の説明を終わります。 |