I will talk about two nice properties of the move semantic in this post that is not so often mentioned. Containers of the standard template library (STL) can have non-copyable elements. The copy semantic is the fallback for the move semantic. Irritated? I hope so!
Moving Instead of Copying
Do you remember the program packagedTask.cpp from the post Asynchronous callable wrappers? Of course, not. Here, once more.
Moving elements in a container
I’m not interested in the program that calculates the sum of the numbers from 0 .. 10000 in four threads.
I’m interested in a completely different property of std:::packaged_task. std::packaged_task is not copyable. The reason is simple. The copy constructor and copy assignment operator are set to delete. You can read the details here: cppreference.com.
How is it possible to use std::package_task as an element in a container of the STL? Containers of the STL want to own their elements. Therefore, I move via std::move the std::package_task objects (lines 41 – 44) into the container std::deque. Consequently, I must use the move semantic in lines 52 and 54 because I can not copy the std::package_task.
But that is not the end of the story. If an algorithm of the STL uses, under the hood, no copy semantics, you can apply it to containers with non-copyable elements. You will get a compiler error if the algorithm uses internal copy semantics.
The algorithm on only moveable elements
In the next example, I make it very simple. I define a simple wrapper MyInt for natural numbers.
I only declaratively use delete (lines 13 and 14) for the copy semantic and default (lines 17 and 18) for the move semantic. Therefore, the compiler will do the right job for me. I implement only the constructor and the getter getVal (lines 20 – 22). Although my type is non-copyable, I use it in a std::for_each (line 36) and std::accumulate (line 40) algorithm of the STL.
There are no big surprises.
The program will not compile with cl.exe
Unfortunately, the program will not compile with a recent cl.exe Compiler (19.10.24807.0 (x86)). Microsoft std::accumulate versions use, under the hood, copy semantics. This is opposite to recent GCC or clang compilers, which use move semantics. But cl.exe is right. std::accumulate requires that T must be copied, assignable, and copy constructible. This will not hold for MyInt. This issue is still under discussion: https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/ext/lwg-active.html
The copy semantic is a fallback for the move semantic. What does that mean?
Copy Semantics as a Fallback for Move Semantics
If I write an algorithm that internally uses move semantics, I can apply that algorithm to non-copyable types. I have only to change my type MyInt.
MyInt has a user-defined copy constructor and copy assignment operator. Therefore, the compiler will not automatically generate a move constructor or move assignment operator. You can read the details here (move semantic) or ask the type traits library (lines 40 and 41) for help. Sadly, my GCC doesn’t support this function of the type traits library. So I have to use a more recent GCC 5.2. The critical point is that instances of MyInt can be used in the function template swapMove (lines 7 – 12), although these instances don’t support move semantics.
The reason is: A rvalue can be bound to
- a constant lvalue reference.
- a non-constant rvalue reference.
The non-constant rvalue reference has a higher priority than the constant lvalue reference. A copy constructor or a copy assignment operator expects its arguments as a constant lvalue reference. A move constructor or a move assignment operator expects its arguments as a non-constant rvalue reference. What sounds a little bit confusing has a lovely property.
Keep the performance in your mind
You can implement functions like swapMove with move semantics in mind. If your data types are not moveable, the functions will also work for only copyable types. The compiler will use the classic copy semantic as a fallback. Therefore, you can comfortably migrate an old C++ codebase to modern C++. Your program is correct in the first iteration and fast in the second.
Writing function temples that can identically forward their arguments, was a ” … a heretofore unsolved problem in C++.“. (Bjarne Stroustrup). This was because since C++11 std::forward we can use perfect forwarding. Read the details in the next post.
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, 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, Rob North, Bhavith C Achar, and Marco Parri Empoli.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
|My special thanks to Embarcadero|
|My special thanks to PVS-Studio|
|My special thanks to Tipi.build|
|My special thanks to Take Up Code|
I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
- Embedded Programmierung mit modernem C++ 12.12.2023 – 14.12.2023 (Präsenzschulung, Termingarantie)
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++
- Clean Code with Modern C++
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: schulung@ModernesCpp.de
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++ Mentoring,