web-dev-qa-db-ja.com

decltypeとauto

私が理解しているように、decltypeautoのどちらも、何かのタイプを理解しようとします。

定義すると:

int foo () {
    return 34;
}

次に、両方の宣言は合法です。

auto x = foo();
cout << x << endl;

decltype(foo()) y = 13;
cout << y << endl;

decltypeautoの主な違いは何ですか?

46
James Leonard

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"
 }

autodecltypeのどちらか一方のみが可能な場所についてのDavidRodríguezの回答も参照してください。

44
Mankarse

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は、戻り値の型など、変数ではない何かの型が必要な場合に使用するのが適切です。

0
Ankur

@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;

}
0
J.Doe