Articles & Books

C++ User Group Meetings in December

The monthly listing of upcoming C++ User Group Meetings on Meeting C++:

C++ User Group Meeting in December 2015

by Jens Weller

From the article:

The montly overview on C++ User Group meetings, this time for December. Meeting C++ is just a few days away, so I'm excited to see that again, so many groups are meeting. Also there are few new user groups worth mentioning! 2 x India (Delhi, Udaipur), Sydney, Beijing, Zürich, Sacramento and Ann Arbor! A new trend seems to be to form learning groups and meet weekly for a in depth C++ tutorial...

Quick Q: Why destructor disabling the generation of implicit move functions?

Quick A: Because it means that your class is handling a ressource, thus the compiler cannot know how to move.

Recently on SO:

Why destructor disabling the generation of implicit move functions?

"The Rule of Zero" is in fact about something else than what special member functions are generated and when. It is about a certain attitude to class design. It encourages you to answer a question:

Does my class manage resources?

If so, each resource should be moved to its dedicated class, so that your classes only manage resources (and do nothing else) or only accumulate other classes and/or perform same logical tasks (but do not manage resources).

It is a special case of a more general Single Responsibility Principle.

When you apply it, you will immediately see that for resource-managing classes you will have to define manually move constructor, move assignment and destructor (rarely will you need the copy operations). And for the non-resource classes, you do not need to (and in fact you probably shouldn't) declare any of: move ctor/assignment, copy ctor/assignment, destructor.

Hence the "zero" in the name: when you separate classes to resource-managing and others, in the "others" you need to provide zero special member functions (they will be correctly auto-generated.

There are rules in C++ what definition (of a special member function) inhibits what other definitions, but they only distract you from understanding the core of the Rule of Zero.

For more information, see:

Quick Q: const-reference qualified member function

Quick A: Delete the r-value reference overload of the function.

Recently on SO:

const-reference qualified member function

A temporary can be bound to a const& qualified object and the ref-qualifier effectively qualifies the implicitly passed object (*this). If you want to prevent calls on temporaries but allow lvalues, you can = delete the rvalue reference overload and implement the lvalue version. Using const qualified reference qualifiers for both operators requires just one implemented and one = deleted implementation:

class File {
    // ...
    FILE* _file;
public:
    operator FILE*() const&& = delete;
    operator FILE*() const& { return this->_file; }
    // ...
};

The net-effect is that you can use the conversion only for objects to which you go an lvalue:

int main() {
    File       f;
    File const cf{};

    FILE* fp = f;              // OK
    FILE* cfp = cf;            // OK
    FILE* tfp = File();        // ERROR: conversion is deleted
    FILE* mfp = std::move(cf); // ERROR: conversion is deleted 
}

Quick Q: std::timed_mutex::try_lock* fail spuriously

Quick A: it is authorized to do so for performance reasons.

Recently on SO:

Quick Q: std::timed_mutex::try_lock* fail spuriously

According to: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3209.htm

On the other hand, there are strong reasons to require that programs be written to tolerate spurious try_lock() failures:

  1. As pointed out in Boehm, Adve, "Foundations of the C++ Concurrency Memory Model", PLDI 08, enforcing sequential consistency for data-race-free programs without spurious try_lock() failures requires significantly stronger memory ordering for lock() operations on try_lock()-compatible mutex types. On some architectures that significantly increases the cost of uncontended mutex acquisitions. This cost appears to greatly outweigh any benefit from prohibiting spurious try_lock() failures.
  2. It allows a user-written try_lock() to fail if, for example, the implementation fails to acquire a low-level lock used to protect the mutex data structure. Or it allows such an operation to be written directly in terms of compare_exchange_weak.
  3. It ensures that client code remains correct when, for example, a debugging thread is introduced that occasionally acquires locks in order to be able to read consistent values from a data structure being checked or examined. Any code that obtains information from try_lock() failure would break with the introduction of another thread that purely locks and reads the data structure.

Overload resolution -- Andrzej KrzemieĊ„ski

An introduction to function template specialization, function (template) overloading, argument dependent lookup (ADL) and overload resolution:

Overload resolution

by Andrzej Krzemieński

From the article:

This post is an introduction to another one that I intend to write in the future...

Breaking all the Eggs in C++ -- Scott Meyers

Scott Meyers takes a deeper look into uninitialized memory in his recent blog post.

Breaking all the Eggs in C++

by Scott Meyers

From the article:

If you want to make an omelet, so the saying goes, you have to break a few eggs. Think of the omelet you could make if you broke not just a few eggs, but all of them! Then think of what it'd be like to not just break them, but to replace them with newer, better eggs. That's what this post is about: breaking all the eggs in C++, yet ending up with better eggs than you started with.

NULL, 0, and nullptr

NULL came from C. It interfered with type-safety (it depends on an implicit conversion from void* to typed pointers), so C++ introduced 0 as a better way to express null pointers. That led to problems of its own, because 0 isn't a pointer, it's an int. C++11 introduced nullptr, which embodies the idea of a null pointer better than NULL or 0. Yet NULL and 0-as-a-null-pointer remain valid. Why? If nullptr is better than both of them, why keep the inferior ways around?

Backward-compatibility, that's why. Eliminating NULL and 0-as-a-null-pointer would break exiting programs. In fact, it would probably break every egg in C++'s basket. Nevertheless, I'm suggesting we get rid of NULL and 0-as-a-null-pointer, thus eliminating the confusion and redundancy inherent in having three ways to say the same thing (two of which we discourage people from using).

Introduction to Variable Templates of C++14--Yu Xuan Zhang

Do you know about variable templates?

Introduction to Variable Templates of C++14

by Yu Xuan Zhang

From the article:

The variable template, which comes from N3651, is one of the major proposals in Standard C++14. The main purpose of the variable template is to simplify definitions and uses of parameterized constants.

Rules before C++14 do not allow declaring a variable using a template declaration. There are workarounds for this problem before C++14, but they are either redundant or complicated...