型推論とは
簡単に言えば、関数の戻り値型などが自明である場合、それを受ける変数の型などをコンパイラに判断させる作業のことです。
型推論をコンパイラが行うことで、ソースコードが簡潔になり可読性が良くなります。
C++でコンパイラに型推論を行わせる方法は、autoキーワードを使用する方法と、decltypeキーワードを使用する方法の二種類あります。
autoによる型推論
関数の戻り値を受け取る変数の型を指定するとき、関数の戻り値の型はコンパイラにとっては自明であるため、autoキーワードを変数の型として指定することができます。
void func() {
std:vector<int> values {1, 2, 3, 4};
auto sum = 0;
for (auto i = values.begin(); i != values.end(); ++i) {
sum += *i;
}
std::cout << "sum = " << sum << std::endl;
}
autoを使用しない場合は、次のようにかなり冗長になります。
void func() {
std:vector<int> values {1, 2, 3, 4};
int sum = 0;
for (std::vector<int>::const_iterator i = values.begin(); i != values.end(); ++i) {
sum += *i;
}
std::cout << "Sum = " << sum << std::endl;
}
decltypeによる型推論
変数を定義する時点でその変数の型を明確に定義できない場合、decltypeキーワードを使用してその問題を解決することができます。
int add(int a, int b) {
return a + b;
}
long add(long a, long b) {
return a + b;
}
template<typename T>
void func(T v1, T v2) {
decltype(add(v1, v2)) result;
result = add(v1, v2);
std::cout << "Result = " << result << std::endl;
}
ただし、上記の場合はautoキーワードを使ったほうが簡潔になります。
int add(int a, int b) {
return a + b;
}
long add(long a, long b) {
return a + b;
}
template<typename T>
void func(T v1, T v2) {
auto result = add(v1, v2);
std::cout << "Result = " << result << std::endl;
}
autoとdecltypeをどのように使い分けるか
変数の型を指定する場合は、autoキーワードを指定すればよいかと思います。decltypeを使用するケースとしては、関数の戻り値の型を指定する場合になります。
template<typename T1, typename T2>
auto add(T1 v1, T2 v2) -> decltype(v1 + v2) {
return v1 + v2;
}
decltypeの読み方
"でくるたいぷ"と読むらしい。