intermediate

A Free Ebook on C++ Smart Pointers--Jonathan Boccara

Nice way to learn more.

A Free Ebook on C++ Smart Pointers

by Jonathan Boccara

From the article:

To write expressive code in C++, mastering smart pointers is a necessity! Without them, our code becomes littered with memory management, news and delete, and unclear semantics about who owns what resources.

If you’re part of my mailing list (which you can join at the bottom of this post), you will get as a Christmas gift a free ebook of more than 50 pages of selected contents of Fluent C++ about smart pointers. Of course, you also get access to the ebook if you’re a Patron of Fluent C++...

How to Design Function Parameters That Make Interfaces Easier to Use (3/3)--Jonathan Boccara

The end.

How to Design Function Parameters That Make Interfaces Easier to Use (3/3)

by Jonathan Boccara

From the article:

This is the final article in the series about function parameters. This series contains:

  • Part 1: interface-level parameters, one-parameter functions, const parameters,
  • Part 2: calling contexts, strong types, parameters order,
  • Part 3: packing parameters, processes, levels of abstraction.

Quick Q: Type inference of 'auto' when using range-for loop in multidimensional arrays

Quick A: a pointer has no size information.

Recently on SO:

Type inference of 'auto' when using range-for loop in multidimensional arrays

The type of row is deduced to be int*. That means, just like any other int*, the compiler doesn't know how big the array it points to is, or even that it's a pointer to the first element of an array at all. All of that information is lost when an array decays into a pointer to its first element.

If instead you use something like

for (auto& row : ia) //<-- NOTE: row is now a reference
    for (int* j = std::begin(row); j != std::end(row); ++j)
        std::cout << *j << '\n';

then the type of row will be deduced to int (&)[4]: reference to an array of 4 ints. The length information is retained, so std::begin and std::end have the information they need.

PS: Just as a note: range-for works by using std::begin and std::end internally, so the above can be a bit more concisely written as

for (auto& row : ia)
    for (auto j : row)
        std::cout << j << '\n';

Python-Like enumerate() In C++17--Nathan Reed

Handy little piece of code.

Python-Like enumerate() In C++17

by Nathan Reed

From the article:

Python has a handy built-in function called enumerate(), which lets you iterate over an object (e.g. a list) and have access to both the index and the item in each iteration. You use it in a for loop, like this:

for i, thing in enumerate(listOfThings):
    print("The %dth thing is %s" % (i, thing))

Iterating over listOfThings directly would give you thing, but not i, and there are plenty of situations where you’d want both (looking up the index in another data structure, progress reports, error messages, generating output filenames, etc).

C++ range-based for loops work a lot like Python’s for loops. Can we implement an analogue of Python’s enumerate() in C++? We can!

Quick Q: Regarding shared_ptr reference count block

Quick A: it is an implementation detail for the std.

Recently on SO:

Regarding shared_ptr reference count block

(1) Regarding size: How can I programatically find the exact size of the control block for a std::shared_ptr?

There is no way. It's not directly accessible.

(2) Regarding logic: Additionally, boost::shared_ptr mentions that they are completely lock-free with respect to changes in the control block.(Starting with Boost release 1.33.0, shared_ptr uses a lock-free implementation on most common platforms.) I don't think std::shared_ptr follows the same - is this planned for any future C++ version? Doesn't this also mean that boost::shared_ptr is a better idea for multithreaded cases?

Absolutely not. Lock-free implementations are not always better than implementations that use locks. Having an additional constraint, at best, doesn't make the implementation worse but it cannot possibly make the implementation better.

Consider two equally competent programmers each doing their best to implement shared_ptr. One must produce a lock-free implementation. The other is completely free to use their best judgment. There is simply no way the one that must produce a lock-free implementation can produce a better implementation all other things being equal. At best, a lock-free implementation is best and they'll both produce one. At worse, on this platform a lock-free implementation has huge disadvantages and one implementer must use one. Yuck.