intermediate

Word Counting in C++: Implementing a Simple Word Counter—Jonathan Boccara

Useful to learn.

Word Counting in C++: Implementing a Simple Word Counter

by Jonathan Boccara

From the article:

Word counts can reveal information about your code, or make an unknown piece of code more expressive to your eyes.

There are online tools to count words in generic text, but most of those I’ve come across are designed around counting words in text and SEO (Search Engine Optimization). Since analysing source code is not the same thing as analysing the text of a blog post, let’s design a tool fit for our needs of counting words in code. This way, we will be able to make it evolve when we discover new tasks to try with our word counter.

Another reason to write our own word counter is that it will let us practice interface design, and also STL algorithms, which are useful to master for coding in C++.

For this first version of our word counter, the objective will be to put together a working prototype. Then we will improve it over future posts, by adding features and by refining its implementation...

Quick Q: constexpr specifier performance did’t meet my expectations in C++

Quick A: a constexpr function does not imply it will be evaluated at compile time.

Recently on SO:

constexpr specifier performance did't meet my expectations in C++

Your constexpr function requires way too much computation to do in a compiler, that's why the compiler chooses to delay it to runtime execution.

You can change this line:

static const auto c_x = c_fun(40);

to:

constexpr auto c_x = c_fun(40);

to see compiler's output. On clang, it tells me:

note: constexpr evaluation hit maximum step limit;
c_x is indeed a compile-time constant, but the compiler can't compute it due to implementation limitation. Note that your function has exponential complexity.

Everything will be fine if you change 40 to some reasonable number, like 10:

constexpr auto c_x = c_fun(10);

std::any: How, when, and why—Casey Carter

Do you use it?

std::any: How, when, and why

by Casey Carter

From the article:

C++17 adds several new “vocabulary types” – types intended to be used in the interfaces between components from different sources – to the standard library. MSVC has been shipping implementations of std::optional, std::any, and std::variantsince the Visual Studio 2017 release, but we haven’t provided any guidelines on how and when these vocabulary types should be used. This article on std::any is the second of a series that examines each of the vocabulary types in turn...

“auto to stick” and Changing Your Style—Jonathan Boccara

What do you think?

“auto to stick” and Changing Your Style

by Jonathan Boccara

From the article:

While performing a code review on a refactoring project, I stumbled upon a change that took a line of code from this state:

Widget myWidget{42};

to that:

auto myWidget = Widget{42};

Well, in the actual case the type wasn’t called Widget and the initialization value wasn’t exactly 42. But that’s the gist of it...

Modern C++ Features – Quality-of-Life Features—Arne Mertz

Some to help, some to enable.

Modern C++ Features – Quality-of-Life Features

by Arne Mertz

From the article:

With the new C++ standards, we got a lot of features that feel like “quality-of-life” features. They make things easier for the programmer but do not add functionality that wasn’t already there. Except, some of those features do add functionality we couldn’t implement manually.

Some of those quality-of-life features are really exactly that. The standard often describes them as being equivalent to some alternative code we can actually type. Others are mostly quality-of-life, but there are edge cases where we can not get the effect by hand, or the feature is slightly superior to the manual implementation.

I will concentrate on core language features here, since most library features are implementable using regular C++. Only a few library features use compiler intrinsics...

Quick Q: C++11 auto: what if it gets a constant reference?

Quick A: auto never deduces a reference.

Recently on SO:

C++11 auto: what if it gets a constant reference?

Read this article: Appearing and Disappearing consts in C++

Type deduction for auto variables in C++0x is essentially the same as for template parameters. (As far as I know, the only difference between the two is that the type of auto variables may be deduced from initializer lists, while the types of template parameters may not be.) Each of the following declarations therefore declare variables of type int (never const int):

auto a1 = i;
auto a2 = ci;
auto a3 = *pci;
auto a4 = pcs->i;

During type deduction for template parameters and auto variables, only top-level consts are removed. Given a function template taking a pointer or reference parameter, the constness of whatever is pointed or referred to is retained:

template<typename T>
void f(T& p);

int i;
const int ci = 0;
const int *pci = &i;

f(i);               // as before, calls f<int>, i.e., T is int
f(ci);              // now calls f<const int>, i.e., T is const int
f(*pci);            // also calls f<const int>, i.e., T is const int

This behavior is old news, applying as it does to both C++98 and C++03. The corresponding behavior for auto variables is, of course, new to C++0x:

auto& a1 = i;       // a1 is of type int&
auto& a2 = ci;      // a2 is of type const int&
auto& a3 = *pci;    // a3 is also of type const int&
auto& a4 = pcs->i;  // a4 is of type const int&, too

Since you can retain the cv-qualifier if the type is a reference or pointer, you can do:

auto& my_foo2 = GetFoo();

Instead of having to specify it as const (same goes for volatile).

Edit: As for why auto deduces the return type of GetFoo() as a value instead of a reference (which was your main question, sorry), consider this:

const Foo my_foo = GetFoo();

The above will create a copy, since my_foo is a value. If auto were to return an lvalue reference, the above wouldn't be possible.

How To Use std::visit With Multiple Variants—Bartlomiej Filipek

Variant utility.

How To Use std::visit With Multiple Variants

by Bartlomiej Filipek

From the article:

std::visit is a powerful utility that allows you to call a function over a currently active type in std::variant. It does some magic to select the proper overload, and what’s more, it can support many variants at once.

Let’s have a look at a few examples of how to use this functionality...

Quick Q: C++ constexpr - Value can be evaluated at compile time?

Quick A: if parameter are not known at compile time, it is like a normal function

Recently on SO:

C++ constexpr - Value can be evaluated at compile time?

The quoted wording is a little misleading in a sense. If you just take PlusOne in isolation, and observe its logic, and assume that the inputs are known at compile-time, then the calculations therein can also be performed at compile-time. Slapping the constexpr keyword on it ensures that we maintain this lovely state and everything's fine.

But if the input isn't known at compile-time then it's still just a normal function and will be called at runtime.

So the constexpr is a property of the function ("possible to evaluate at compile time" for some input, not for all input) not of your function/input combination in this specific case (so not for this particular input either).

It's a bit like how a function could take a const int& but that doesn't mean the original object had to be const. Here, similarly, constexpr adds constraints onto the function, without adding constraints onto the function's input.

Admittedly it's all a giant, confusing, nebulous mess (C++! Yay!). Just remember, your code describes the meaning of a program! It's not a direct recipe for machine instructions at different phases of compilation.

(To really enforce this you'd have the integer be a template argument.)

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...