advanced

Without form and void—Barry Revzin

Did you encounter the problem?

Without form and void

by Barry Revzin

From the article:

In C++, void is a pretty strange thing. We can cast expressions to void, throw-expressions have void type, void* can point to anything, and void functions can actually return back to the caller. But we can’t have objects of type void or even write a type like void&. A function declaration like void f(void) is actually a nullary function. It’s a bit weird — but it’s not something a lot of people lose sleep over.

Until it starts wreaking havoc on your generic code — because it’s like the vector<bool> of the type system...

[[trivial_abi]] 101—Arthur O’Dwyer

Interesting!

[[trivial_abi]] 101

by Arthur O’Dwyer

From the article:

Finally, a blog post on [[trivial_abi]]!

This is a brand-new feature in Clang trunk, new as of about February 2018. It is a vendor extension to the C++ language — it is not standard C++, it isn’t supported by GCC trunk, and there is no active WG21 proposal to add it to the standard C++ language, as far as I know...

“Modern C++ Template Programming” with Nicolai Josuttis

Meeting C++ 2018 offers also a workshop with Nicolai Josuttis:

Modern C++ Template Programming

by Jens Weller

From the article:

Each and every C++ programmer uses templates. Containers such as vector<> or array<>, strings, algorithms such as sort(), iterators, and I/O streams are all implemented as generic code. Modern C++ adds type traits, smart pointers, and template member functions such as emplace(), and generic lambdas as a tricky form of generic code.

Nevertheless the knowledge and understanding of how to implement and use templates is very limited and each and every programmer is sooner or later getting uncertain.

This workshop therefore discusses templates for a whole day to make clear what it means to use templates and how to use them in practice. As a result the general understanding of templates will be improved and generic code might become more helpful and less surprising.

Quick Q: int a[] = {1,2,}; Weird comma allowed. Any particular reason?

Quick A: For convenience.

Recently on SO:

int a[] = {1,2,}; Weird comma allowed. Any particular reason?

It makes it easier to generate source code, and also to write code which can be easily extended at a later date. Consider what's required to add an extra entry to:

int a[] = {
   1,
   2,
   3
};

... you have to add the comma to the existing line and add a new line. Compare that with the case where the three already has a comma after it, where you just have to add a line. Likewise if you want to remove a line you can do so without worrying about whether it's the last line or not, and you can reorder lines without fiddling about with commas. Basically it means there's a uniformity in how you treat the lines.

Now think about generating code. Something like (pseudo-code):

output("int a[] = {");
for (int i = 0; i < items.length; i++) {
    output("%s, ", items[i]);
}
output("};");

No need to worry about whether the current item you're writing out is the first or the last. Much simpler.

uninitialized_tag in C++—Marius Elvert

Optimise or not?

uninitialized_tag in C++

by Marius Elvert

From the article:

No doubt, C++ is one of those languages you can use to squeeze out every last drop of your CPU’s processing power. On the other hand, it also allows a high amount of abstraction. However, micro-optimization seldom works well with nice abstractions...

C++17: The two line visitor explained—Marius Elvert

The power of C++17.

C++17: The two line visitor explained

by Marius Elvert

From the article:

If you have ever used an “idiomatic” C++ variant datatype like Boost.Variant or the new C++17 std::variant, you probably wished you could assemble a visitor to dispatch on the type by assembling a couple of lambda expressions like this:

auto my_visitor = visitor{
  [&](int value) { /* ... */ },
  [&](std::string const& value) { /* ... */ },
};

Quick Q: With “-fno-exceptions”, what happens with “new T”?

Quick A: The behaviour will likely stay the same.

Recently on SO:

With “-fno-exceptions”, what happens with “new T”?

The way I understand it, operator new is defined by libstdc++. If you now compile your own code with -fno-exceptions, you cannot catch any exceptions, but you will still be linking against the normal version of libstdc++, which does throw an exception.

So yes, new T will throw an exception, even with -fno-exception.

However, if you compiled libstdc++ with -fno-exception as well, things become different. Now, new T cannot throw an exception but, if I read the libstdc++ manual right it will call abort() instead.

It seems that, if you want your new T to return NULL on failure, the only way is to explicitely specify nothrow...

Quick Q: Does access control matter for deleted constructors?

Quick A: No

Recently on SO:

Does access control matter for deleted constructors?

Since it's overload resolution that makes the program ill-formed in this case, and not access specifiers (which are checked later), there is no difference in outcome. The compiler will always complain that a deleted function was picked.

But since the idiom before C++11 was "declare but not define a private copy c'tor to disable copying", I would consider it going along with the same idiom, and therefore favorable. You are using the "old slang" with some new language to describe the same thing, except better.

Guidelines For Rvalue References In APIs—Jonathan Müller

Everything you need to know.

Guidelines For Rvalue References In APIs

by Jonathan Müller

From the article:

I’ll be giving a talk at ACCU about when to use which pointer types and why.

While working on that I made some guidelines for rvalue references in interfaces which didn’t quite fit the talk, so I’m writing about them here.

When should you use rvalue references as function parameters?

When as return types?

What are ref-qualified member functions and when and how should you use them?

Let’s tackle it one by one...