私が理解しているように、decltype
とauto
のどちらも、何かのタイプを理解しようとします。
定義すると:
int foo () {
return 34;
}
次に、両方の宣言は合法です。
auto x = foo();
cout << x << endl;
decltype(foo()) y = 13;
cout << y << endl;
decltype
とauto
の主な違いは何ですか?
decltype
は、それに渡される式のdeclaredタイプを示します。 auto
は、テンプレートタイプの控除と同じことを行います。したがって、たとえば、参照を返す関数がある場合でも、auto
は値になります(auto&
は参照を取得します)、ただしdecltype
は正確に戻り値の型になります。
#include <iostream>
int global{};
int& foo()
{
return global;
}
int main()
{
decltype(foo()) a = foo(); //a is an `int&`
auto b = foo(); //b is an `int`
b = 2;
std::cout << "a: " << a << '\n'; //prints "a: 0"
std::cout << "b: " << b << '\n'; //prints "b: 2"
std::cout << "---\n";
decltype(foo()) c = foo(); //c is an `int&`
c = 10;
std::cout << "a: " << a << '\n'; //prints "a: 10"
std::cout << "b: " << b << '\n'; //prints "b: 2"
std::cout << "c: " << c << '\n'; //prints "c: 10"
}
auto
とdecltype
のどちらか一方のみが可能な場所についてのDavidRodríguezの回答も参照してください。
auto
(型を推測するコンテキスト)は、初期化子が存在する変数の型の定義に限定されます。 decltype
はより広い構成体であり、追加の情報を犠牲にして、式のタイプを推測します。
auto
を使用できる場合は、型を推定する式を指定する必要がないため、decltype
よりも簡潔です。
auto x = foo(); // more concise than `decltype(foo()) x`
std::vector<decltype(foo())> v{ foo() }; // cannot use `auto`
キーワードauto
は、関数に後続の戻り値の型を使用する場合、完全に無関係なコンテキストでも使用されます。
auto foo() -> int;
auto
はリーダーにすぎないため、コンパイラーはこれが末尾の戻り値型の宣言であることを認識します。上記の例は簡単に古いスタイルに変換できますが、一般的なプログラミングでは便利です。
template <typename T, typename U>
auto sum( T t, U u ) -> decltype(t+u)
この場合、auto
を使用して戻り値の型を定義することはできません。
一般に、初期化する変数の型が必要な場合は、autoを使用します。 decltypeは、戻り値の型など、変数ではない何かの型が必要な場合に使用するのが適切です。
@Mankarseのサンプルコードを変更します。
#include <iostream>
int global = 0;
int& foo()
{
return global;
}
int main()
{
decltype(foo()) a = foo(); //a is an `int&`
auto b = foo(); //b is an `int`
b = 2;
std::cout << "a: " << a << '\n'; //prints "a: 0"
std::cout << "b: " << b << '\n'; //prints "b: 2"
std::cout << "global: " << global << '\n'; //prints "global: 0"
std::cout << "---\n";
//a is an `int&`
a = 10;
std::cout << "a: " << a << '\n'; //prints "a: 10"
std::cout << "b: " << b << '\n'; //prints "b: 2"
std::cout << "global: " << global << '\n'; //prints "global: 10"
return 0;
}