intermediate

Modern C++: 7 Ways to Fake It Until You Have It—Jonathan Boccara

If you want.

Modern C++: 7 Ways to Fake It Until You Have It

by Jonathan Boccara

From the article:

Do you wish you had a later version of C++ in your production code? If you do, you’re not alone: a lot of C++ developers today don’t work with a compiler that supports the latest version of the standard.

It could be for many reasons: perhaps you have a lot of legacy code to migrate, or your clients do, or your hardware doesn’t have the adequate infrastructure yet. The point is, you can’t benefit from the latest features that the language offers, and that’s a shame because some of them would surely make your code more expressive.

But even if you can’t use those features, you don’t have to give up on their benefits. At least some of their benefits. There are way you could use the ideas of the new features in your code, to convey your intents more precisely.

Sure enough, it’s not as good as having them natively, which is why updating your compilers is still a necessity. But in the meantime, here are 7 ways to emulate those features, that will improve your code at a minimal cost...

Spaceship Operator—Simon Brand

The future?

Spaceship Operator

by Simon Brand

From the article:

You write a class. It has a bunch of member data. At some point, you realise that you need to be able to compare objects of this type. You sigh and resign yourself to writing six operator overloads for every type of comparison you need to make. Afterwards your fingers ache and your previously clean code is lost in a sea of functions which do essentially the same thing. If this sounds familiar, then C++20’s spaceship operator is for you. This post will look at how the spaceship operator allows you to describe the strength of relations, write your own overloads, have them be automatically generated, and how correct, efficient two-way comparisons are automatically rewritten to use them...

How to Design Early Returns in C++ (Based on Procedural Programming)—Jonathan Boccara

What do you think?

How to Design Early Returns in C++ (Based on Procedural Programming)

by Jonathan Boccara

From the article:

Travelling back from ACCU conference a couple of weeks ago, one of the insights that I’ve brought back with me is from Kevlin Henney’s talk Procedural Programming: It’s Back? It Never Went Away. It’s surprisingly simple but surprisingly insightful, and it has to do with early return statements...

Quick Q: What are copy elision and return value optimization?

Quick A: they are common optimizations that a compiler can do behind the scenes to avoid copying in certain cases.

Recently on SO:

What are copy elision and return value optimization?

Copy elision is an optimization implemented by most compilers to prevent extra (potentially expensive) copies in certain situations. It makes returning by value or pass-by-value feasible in practice (restrictions apply).

It's the only form of optimization that elides (ha!) the as-if rule - copy elision can be applied even if copying/moving the object has side-effects.

The following example taken from Wikipedia:

struct C {
  C() {}
  C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
  return C();
}

int main() {
  std::cout << "Hello World!\n";
  C obj = f();
}

Depending on the compiler & settings, the following outputs are all valid:

Hello World!
A copy was made.
A copy was made.
Hello World!
A copy was made.
Hello World!

This also means fewer objects can be created, so you also can't rely on a specific number of destructors being called. You shouldn't have critical logic inside copy/move-constructors or destructors, as you can't rely on them being called.

If a call to a copy or move constructor is elided, that constructor must still exist and must be accessible. This ensures that copy elision does not allow copying objects which are not normally copyable, e.g. because they have a private or deleted copy/move constructor.

C++17: As of C++17, Copy Elision is guaranteed when an object is returned directly:

struct C {
  C() {}
  C(const C&) { std::cout << "A copy was made.\n"; }
};

C f() {
  return C(); //Definitely performs copy elision
}
C g() {
    C c;
    return c; //Maybe performs copy elision
}

int main() {
  std::cout << "Hello World!\n";
  C obj = f(); //Copy constructor isn't called
}

Should I Use Overloads or Default Parameters?—Jonathan Boccara

The answer is not obvious.

Should I Use Overloads or Default Parameters?

by Jonathan Boccara

From the article:

“Should I use overloads or default parameters”, haven’t you asked yourself that question?

When designing an interface where the user can leave the value of an argument up to the API, two approaches are possible:

Using a default parameters:

voiddrawPoint(int x, int y, Color color = Color::Black);
void drawPoint(int x, int y, Color color = Color::Black);

And using overloading:

void drawPoint(int x, int y); // draws a point in black
void drawPoint(int x, int y, Color color);

Which approach is cleaner? Which expresses better the intentions of the interface? Or is it just a matter of style?

This may be subjective, but I’m under the impression that overloading tends to have better popularity than default parameters amongst C++ developers. But I believe that both features have their usages, and it’s usefulto see what makes one or the other more adapted to a given situation.

In-Place Construction for std::any, std::variant and std::optional—Bartlomiej Filipek

Efficient construction.

In-Place Construction for std::any, std::variant and std::optional

by Bartlomiej Filipek

From the article:

When you read articles or reference pages for std::any, std::optional or std::variant you might notice a few helper types called in_place_* available in constructors.

Why do we need such syntax? Is this more efficient than “standard” construction?

C++17: Attributes—Marc Gregoire

Another new feature.

C++17: Attributes

by Marc Gregoire

From the article:

C++17 introduces three new code attributes:

  • [[fallthrough]]
  • [[maybe_unused]]
  • [[nodiscard]]

The first one was discussed in detail in my C++17: Fallthrough in switch statements blog post. The others are briefly explains below...

Quick Q: Accessing protected members in a derived class

Quick A: Only your own type can be accessed.

Recently on SO:

Accessing protected members in a derived class

You can only access protected members in instances of your type (or derived from your type).
You cannot access protected members of an instance of a parent or cousin type.

In your case, the Derived class can only access the b member of a Derived instance, not of a different Base instance.

Changing the constructor to take a Derived instance will also solve the problem.

Hello CMake!—Arne Mertz

Do you use it?

Hello CMake!

by Arne Mertz

From the article:

Since I have mentioned CMake in a handful of past blog posts, it is time to give a short introduction for those that don’t know it yet.

CMake is one of the most popular build systems for C++ out there. One of the main reasons probably is that it is cross-platform: It does not build the project itself but operates a platform-specific system. That means it can generate Makefiles, ninja-build files, or project files for Visual Studio or Xcode, to name just a few...