Подтвердить что ты не робот

Decltype vs auto

Как я понимаю, оба decltype и auto будут пытаться выяснить, что это за тип.

Если мы определим:

int foo () {
    return 34;
}

Затем оба объявления являются законными:

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

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

Не могли бы вы рассказать мне, каково главное различие между decltype и auto?

4b9b3361

Ответ 1

decltype дает объявленный тип передаваемого ему выражения. 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.

Ответ 2

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 не может использоваться для определения типа возврата.

Ответ 3

Как правило, если вам нужен тип переменной, которую вы собираетесь инициализировать, используйте авто. decltype лучше использовать, когда вам нужен тип для чего-то, что не является переменной, типа возвращаемого типа.