C++ Insights - Implicit Conversions

Contents[Show]

I'm totally happy to announce that this post starts a series of posts to C++ Insights. C++ Insights is an awesome tool which I use heavily in my posts and in my classes to show the magic of the C++ compiler.

 

01 implicit conversions

This series is motivated by a brief conversation I had with Andreas. I asked him if he has some use case examples which show how C++ Insights can be helpful when teaching. I think there are many things. This article is the start of a series of five posts by Andreas which I will publish at Modernes C++ because I think C++ Insights is an invaluable tool to get a deeper insight in the C++ compiler magic. In case, you are new to C++ Insights consider this introductory article. Without further ado, Andreas post. When you follow the link near to each example, you can directly analyse the example in C++ Insight.

Implicit Conversions

Let’s start with something simple which happens so often: implicit conversations. Sometimes, they are perceived as cumbersome or hidden, sometimes as powerful. For beginners and even for experts in certain debugging situations it is hard to see where implicit conversations happen.

A Basic Example

Consider this basic example:

void UnsignedIntFunction(unsigned int) {}

int main()
{
    int x = 1;
    UnsignedIntFunction(x);
}

With this few lines and knowledge of C++, it is easy to see that UnsignedIntFunction takes an unsigned int while we are passing an int. Aside from the fact that the two types have different ranges on the call side, it works without additional work. This truncation is harder to spot in a bigger code base. For students, it is even harder in my experience. Using C++ Insights gives you the following output:

void UnsignedIntFunction(unsigned int)
{
}


int main()
{
  int x = 1;
  UnsignedIntFunction(static_cast<unsigned int>(x));
}

You can now show that and where the implicit conversion kicks in. The great benefit of C++ Insights as an online tool is that you can change the signature of UnsignedIntFunction to int and see the implicit conversion disappear. This is powerful as your students do not just have to believe you, they can see it an experiment with it themselves. I frequently tell my students not to trust me and challenge what I’m telling them. With C++ Insights they easily can. Sadly for me they sometimes find my mistakes, but that is a different story.

Classes

Let’s move on to something more complex like classes with conversion operators things get more tricky to spot. At this point, we added operator overloading to the picture. The question is, which overload gets selected when? There was a recent tweet by @walletfox illustrating how C++ Insights can help to show which overload of std::cout gets selected. Consider this, cout-free example:

class Foo
{
public:
    Foo(int v)
    : mV{v}
    {
    }

    Foo& operator+=(const Foo& rhs)
    {
        mV += rhs.mV;
        return *this;
    }

    operator int() { return mV; }

private:
    int mV;
};

int main()
{
    Foo t(2);
    t = 3 * 2;

    Foo tt(4);
    t += tt * 2;
}

The question is, do you directly spot what happens for t = 3 * 2 and t += tt * 2? Running C++ Insights on it gives the following output:

class Foo
{
public:
    inline Foo(int v)
    : mV{v}
    {
    }
    
    

    inline Foo & operator+=(const Foo & rhs)
    {
      this->mV += rhs.mV;
      return *this;
    }
    

    using retType = int;
    inline operator retType ()
    {
      return this->mV;
    }
    

private:
    int mV;
/* public: inline constexpr Foo(const Foo &); */
/* public: inline constexpr Foo(Foo &&); */
/* public: inline Foo & operator=(const Foo &); */
/* public: inline Foo & operator=(Foo &&) noexcept; */
/* public: inline ~Foo() noexcept; */
};

int main()
{
  Foo t = Foo(2);
  t.operator=(Foo(3 * 2));
  Foo tt = Foo(4);
  t.operator+=(Foo(static_cast<int>(tt.operator int()) * 2));
}

Aside from the question you can see implicit member-functions the compiler adds like copy and move operations as well as the destructor. You also see the answer to the original question; there are implicit conversions. Both times a temporary object of Foo is created which then gets passed to operator=(const Foo&) and operator+=(const Foo). We did not implement the first one. In addition to all this, the conversion operator operator int() is also used to first convert a Foo object to an int just multiply it by 2 and then pass the result in a temporary Foo object.

Special Member Functions

Another thing C++ Insights shows us, you have already seen it, are the special member functions the compiler generates for us. In the example above, we can see the copy and move constructor as well as the copy and move assignment operators. Here is an example demonstrating it even better:

class A
{
public:
  A() = default;
  A(const A&) {}
};

class B
{
public:
};

int main()
{
  A a;
  A a2;
  //a = a2;
  
  B b;
}

In class A we do provide a copy constructor. With that the compiler does no longer generate the move operations for this class as it does it for B:

class A
{
public:
  A() = default;
  inline A(const A &)
  {
  }
  
  
// public: inline constexpr A() noexcept;
};

class B
{
public:
// public: inline constexpr B() noexcept;
// public: inline constexpr B(const B &);
// public: inline constexpr B(B &&);
};

int main()
{
  A a = A();
  A a2 = A();
  B b = B();
}

What you can see in addition is, that the special members are only generated if needed. In the code as it is, there is no assignment operator. However, if we enable the line a = a2 we get one:

class A
{
public:
  A() = default;
  inline A(const A &)
  {
  }
  
  
// public: inline constexpr A() noexcept;
// public: inline constexpr A & operator=(const A &) noexcept;
};

class B
{
public:
// public: inline constexpr B() noexcept;
// public: inline constexpr B(const B &);
// public: inline constexpr B(B &&);
};

int main()
{
  A a = A();
  A a2 = A();
  a.operator=(a2);
  B b = B();
}

I think that the power of C++ Insights is that you can see how a code change on your side effects what the compiler adds or selects. It’s more or less like the brilliant compiler explorer except for it spits the result out in a language we all understand well.

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 type deduction …

Andreas

 

 

Thanks a lot to my Patreon Supporters: Paul Baxter,  Meeting C++, Matt Braun, Avi Lachmish, Roman Postanciuc, Venkata Ramesh Gudpati, Tobias Zindl, Dilettant, Marko, Ramesh Jangama, G Prvulovic, and Reiner Eiteljörge.

Thanks in particular to:  TakeUpCode 450 60

 

Get your e-book at Leanpub:

The C++ Standard Library

 

Concurrency With Modern C++

 

Get Both as one Bundle

cover   ConcurrencyCoverFrame   bundle
With C++11, C++14, and C++17 we got a lot of new C++ libraries. In addition, the existing ones are greatly improved. The key idea of my book is to give you the necessary information to the current C++ libraries in about 200 pages.  

C++11 is the first C++ standard that deals with concurrency. The story goes on with C++17 and will continue with C++20.

I'll give you a detailed insight in the current and the upcoming concurrency in C++. This insight includes the theory and a lot of practice with more the 100 source files.

 

Get my books "The C++ Standard Library" (including C++17) and "Concurrency with Modern C++" in a bundle.

In sum, you get more than 600 pages full of modern C++ and more than 100 source files presenting concurrency in practice.

 

Get your interactive course

 

Modern C++ Concurrency in Practice

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

educative CLibrary

Based on my book "Concurrency with Modern C++" educative.io created an interactive course.

What's Inside?

  • 140 lessons
  • 110 code playgrounds => Runs in the browser
  • 78 code snippets
  • 55 illustrations

Based on my book "The C++ Standard Library" educative.io created an interactive course.

What's Inside?

  • 149 lessons
  • 111 code playgrounds => Runs in the browser
  • 164 code snippets
  • 25 illustrations

Add comment


My Newest E-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)

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 1364

All 3003059

Currently are 213 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments