decltype vs auto
C++Type InferenceC++ Problem Overview
As I understand it, both decltype
and auto
will attempt to figure out what the type of something is.
If we define:
int foo () {
return 34;
}
Then both declarations are legal:
auto x = foo();
cout << x << endl;
decltype(foo()) y = 13;
cout << y << endl;
Could you please tell me what the main difference between decltype
and auto
is?
C++ Solutions
Solution 1 - C++
decltype
gives the declared type of the expression that is passed to it. auto
does the same thing as template type deduction. So, for example, if you have a function that returns a reference, auto
will still be a value (you need auto&
to get a reference), but decltype
will be exactly the type of the return value.
#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"
}
Also see David Rodríguez's answer about the places in which only one of auto
or decltype
are possible.
Solution 2 - C++
auto
(in the context where it infers a type) is limited to defining the type of a variable for which there is an initializer. decltype
is a broader construct that, at the cost of extra information, will infer the type of an expression.
In the cases where auto
can be used, it is more concise than decltype
, as you don't need to provide the expression from which the type will be inferred.
auto x = foo(); // more concise than `decltype(foo()) x`
std::vector<decltype(foo())> v{ foo() }; // cannot use `auto`
The keyword auto
is also used in a completely unrelated context, when using trailing return types for functions:
auto foo() -> int;
There auto
is only a leader so that the compiler knows that this is a declaration with a trailing return type. While the example above can be trivially converted to old style, in generic programming it is useful:
template <typename T, typename U>
auto sum( T t, U u ) -> decltype(t+u)
Note that in this case, auto
cannot be used to define the return type.
Solution 3 - C++
modify @Mankarse's example code,I think a better one blew:
#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;
}
Solution 4 - C++
Generally, if you need a type for a variable you are going to initialize, use auto. decltype is better used when you need the type for something that is not a variable, like a return type.
Solution 5 - C++
> I consider auto to be a purely simplifying feature whereas the primary purpose of decltype is to enable sophisticated metaprogramming in foundation libraries. They are however very closely related when looked at from a language-technical point of use.
From HOPL20 4.2.1, Bjarne Stroustrup.