Как я понимаю, и decltype
, и auto
будут пытаться определить тип чего-либо.
Если мы определим:
int foo () {
return 34;
}
Тогда оба объявления законны:
auto x = foo();
cout << x << endl;
decltype(foo()) y = 13;
cout << y << endl;
Подскажите, пожалуйста, в чем основное различие между decltype
и auto
?
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"
}
Также смотрите ответ David Rodríguez'а о местах, в которых возможен только один из auto
или decltype
.
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 лучше использовать, когда вам нужен тип для чего-то, что не является переменной, например, для возвращаемого типа.