Hello, I know that both perform type deduction, but what is the difference between the two? When is it more convenient to use decltype
envelope auto
and vice versa?
Hello, I know that both perform type deduction, but what is the difference between the two? When is it more convenient to use decltype
envelope auto
and vice versa?
auto
allows you to deduce the type from the value with which the variable starts:However,
auto
it is not capable of covering the entire range of possibilities...Imagine that you have to program a template such that:
How do you program that template?
Version 1
Valid in C++17, not so in C++11
version 2
Compatible with all versions but a bit cumbersome to use, since although the type
U
can be deduced automatically, the typeT
will have to be indicated explicitly:version 2.1
In order to deduce the two values, we create an intermediate structure as traits :
Although it is easy to understand that this solution begins to be quite cumbersome.
version 3
... or we can also use
decltype
In this case, it
decltype
evaluates the expressionT().otraFunc()
which is nothing more than:T()
: Simulates the creation of a new object of typeT
T().otraFunc()
simulates the call and keeps the return type of the functionotraFunc
for the typeT
It could happen that the default constructor is
T
not available for a given type... in which case the above expression could not be evaluated... We can get a more generic version using pointers:As
decltype
it does not execute code but simply evaluates it, there is no risk of memory leaks or calls on invalid objects... of course we cannot usenew
...By the way, there are people who prefer this other totally valid nomenclature in C++11
Of course
decltype
it can also be used to evaluate simpler expressions:EDIT
Another way to use
decltype
, in combination withdeclval
. So we don't have to worry about how the object should be createdT
:decltype
andauto
they are not interchangeable or equivalent, their use, behavior and purpose is different.auto
is a declarator that infers types in places where a declaration can be made with initialization:const
orvolatile
, these qualifiers will be ignored if applied on the object (first level qualifiers).decltype(...)
is a declarator that copies the type of something already existing:As for when to use them, like any tool: When necessary.
When is it necessary?
There are things that cannot be programmed without the help of
auto
anddecltype
; They are usually things that are impossible (or difficult) for the programmer to know but trivial for the compiler, such as operations between unknown types:In the context of the template function
suma
it is impossible for the programmer to know the return type of the function, we don't know what type it isI
and what type it isD
and we won't know until the moment we instantiate the template, but we can't change the template in ! compile time!Luckily, the compiler has that information that the programmer lacks and knows, at the moment of instantiating the template, what types they are
I
andD
, in this contextauto
, it tells the compiler: " I don't know what type of return the function has but it will be deduced later " whiledecltype
it tells you " Deduce the type of the expressioni + d
and assign it to the return of the functionsuma
".So that:
suma(1, 2.f)
has as return typefloat
.suma<std::string>("patatas", " fritas!")
has as return typestd::string
.For the same reason that leads us to ignore the return type of this function, we cannot create a variable to capture its value:
sub_suma
In the function variablesuper_suma
returns static type deduction (auto
) to the rescue:Note that
super_suma
it does not use-> decltype
after the definition; this is a feature of C++14 known as Function Return Type Deduction .limitations of
auto
anddecltype
The way it works
auto
makes it impossible to derive references unless you do it explicitly:If we wanted to implicitly deduce the return as
const
(which is the actual type) we should rely ondecltype
:As of C++14 it is possible to combine
decltype
andauto
more directly to deduce the actual return type of a function usingdecltype(auto)
:Sometimes it is not necessary, but it is useful.
The declarator
auto
allows us to ignore the type in places where we normally need to duplicate it, for example this:It's more comfortable to read than this:
It also allows us to completely ignore the type so this:
It's more comfortable to read than this:
This type of use
auto
has given rise to a trend called " Almost Alwaysauto
" (in English " Almost Always Auto " or AAA, a term coined by Herb Sutter ) that advises us to use itauto
in almost all situations. The article dedicated to AAA is excellent 1 , I will only translate the parts that I consider most relevant:1 Although I do not fully agree with it.