C++ Insights - Type Deduction

Contents[Show]

Andreas Fertigs story with C++ Insights goes on. This weeks post is about type deduction with auto and decltype or as I often phrase it: "Use the smartness of the compiler."

02 type deduction

Type Deduction

 

With C++11 we got auto and decltype and, therefore, two new forms of type deduction. We are used to type deduction from templates, however, these two new variants can be tricky sometimes.

auto

 

Consider this example:

int main()
{
  int* ip;
  const int* cip;
  const int* const cicp = ip;

  auto aip = ip;
  auto acip = cip;
  auto acicp = cicp;
}

 

We have three different pointers, all of type int. They are getting more and more constified. The question is what’s the type that is deduced by auto? All are pointers, that’s for sure. But what happens with the const? auto removes all top-level qualifier. Hence, even the const disappears. Does it? Here is the output C++ Insights gives:

 

int main()
{

int * ip;
const int * cip;
const int *const cicp = ip;
int * aip = ip;
const int * acip = cip;
const int * acicp = cicp;
}

 

Yes, the top-level const is removed. A constant pointer does not matter, so this const is discarded, but the constness of the memory behind it sticks. Hence, this const is preserved. Which is why acip looks exactly like acicp. This makes sense right.

decltype(auto)

Now, from time to time we like to preserve all qualifiers. This is when decltype appears. In contrast to auto, decltype does preserve all top-level qualifiers. With  C++14 the combination of decltype and auto is possible and we can write decltype(auto) which makes things easier. Here is another example from C++ Insights which uses C++14:

 

int main()
{
  int* ip;
  const int* cip;
  const int* const cicp = ip;

 

  decltype(auto) aip = ip;
  decltype(auto) acip = cip;
  decltype(auto) acicp = cicp;
}

 

From this we get the following output:

 

int main()
{

int * ip;
const int * cip;
const int *const cicp = ip;
int * aip = ip;
const int * acip = cip;
const int *const acicp = cicp;
}

 

We can see, that acicp does carry the second const which is lost when we just use auto.

 

Rainer D 6 P2 540x540Modernes C++ Mentoring

Be part of my mentoring programs:

 

 

 

 

Do you want to stay informed about my mentoring programs: Subscribe via E-Mail.

decltype

When do we need decltype, or more precisely when do we like to keep all qualifiers? One popular reason is templates. Imagine a class template with some function Get. With just using auto it as a return type we can never return a reference to something. In template code, we often don’t know the exact types, which makes it desirable to provide code that just works. decltype can help here. However, consider decltype a library writer feature. In most cases, we are fine with auto. It is just good to know the entire toolbox.

auto& and auto* versus auto

What we‘ve seen so far is, that we need to be explicit, if it comes to auto and references. We must always write auto& to get a reference. How is it with pointers? There auto gives us the correct type, so we can spare the star? This is in fact a question I frequently get from my students. The answer is: it depends. I recommend writing it just for consistency. However, there are scenarios where we indeed need auto* even that auto did deduce the correct type. Consider this example:

struct Foo{};

Foo* GetFoo()
{
   static Foo foo;

   return &foo;
}

int main()
{
  auto fp = GetFoo();
}

 

We have a function returning a Foo* and an auto variable auto f = GetFoo() which deduces the type. Of course, the correct type. What if we’d like to make f const? That we cannot alter the data of f? Sure, we write it like this const auto f = .... At least that’s what we would do if we write it without auto. Here are some possibilities we can try:

struct Foo{};

Foo* GetFoo()
{
   static Foo foo;

   return &foo;
}

int main()
{
   auto fp0 = GetFoo();
   const auto fp1 = GetFoo();
   auto const fp2 = GetFoo();
   //const auto const fp3 = GetFoo(); does not compile
   const auto* fp4 = GetFoo();
   auto* const fp5 = GetFoo();
   const auto* const fp6 = GetFoo();
}

 

First, fp1 produces a const pointer to mutable data. Not exactly what we intended. fp2 probably seems pointless. fp3 makes more sense, but this doesn’t compile. The control changes, if we start using the form auto*. Now, we can add the qualifiers like we can do it with a regular type. But see for yourself in C++ Insights what the result is:

 

struct Foo{/* public: inline constexpr Foo() noexcept; */
/* public: inline constexpr Foo(const Foo &); */
/* public: inline constexpr Foo(Foo &&); */
};

Foo * GetFoo()
{
   static Foo foo = Foo();
   return &foo;
}

int main()
{
   Foo * fp0 = GetFoo();
   Foo *const fp1 = GetFoo();
   Foo *const fp2 = GetFoo();
   const Foo * fp4 = GetFoo();
   Foo *const fp5 = GetFoo();
   const Foo *const fp6 = GetFoo();
}

 

The simple advice is: always be explicit and use the form auto& as well as auto* even if auto is able to deduce a pointer type.

 

Let’s say we are explicit and use auto&. Look at this example:

struct Singleton{};

auto Get()
{
   static Singleton s{};

   return s;
}

int main()
{
   auto& x = Get();
}

 

We have a classical singleton which the function Get should return. Of course, we like a reference to it otherwise we have multiple tons. Despite auto and & this code does not compile:

error: non-const lvalue reference to type 'Singleton' cannot bind to a temporary of type 'Singleton'

The reason is, the Get in fact return Singleton and not Singleton&. Why? Because we did not apply the & to the auto-return type of Get. A small change and the code compiles:

struct Singleton{};

auto& Get()
{
   static Singleton s{};

   return s;
}

int main()
{
   auto& x = Get();
}

 

I’d like to thank Rainer for the opportunity to share information about C++ Insights on his popular blog!

Have fun with C++ Insights. You can support the project by becoming a Patreon or of course with code contributions.

Stay tuned for more insights about C++ Insights to template instantiation …

 

Andreas

 

 

 

Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, and Rob North.

 

Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, and Slavko Radman.

 

 

My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small

 

My special thanks to PVS-Studio PVC Logo

 

My special thanks to Tipi.build tipi.build logo

 

My special thanks to Take Up Code TakeUpCode 450 60

 

Seminars

I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

Bookable (Online)

German

Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.

  • C++ - The Core Language
  • C++ - The Standard Library
  • C++ - Compact
  • C++11 and C++14
  • Concurrency with Modern C++
  • Design Pattern and Architectural Pattern with C++
  • Embedded Programming with Modern C++
  • Generic Programming (Templates) with C++

New

  • Clean Code with Modern C++
  • C++20

Contact Me

Modernes C++,

RainerGrimmDunkelBlauSmall

 

 

Tags: auto, decltype

Stay Informed about my Mentoring

 

Mentoring

English Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Course: The All-in-One Guide to C++20

Course: Master Software Design Patterns and Architecture in C++

Subscribe to the newsletter (+ pdf bundle)

All tags

Blog archive

Source Code

Visitors

Today 3692

Yesterday 5555

Week 33900

Month 55574

All 12133783

Currently are 174 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments