Articles & Books

Trip report: Summer ISO C++ standards meeting (Oulu) -- Herb Sutter

A comprehensive trip report from the just-concluded ISO C++ meeting:

Trip report: Summer ISO C++ standards meeting (Oulu)

by Herb Sutter

From the article:

The big news is that C++ is feature-complete, and on time! We added several more features to the C++17 working paper (see next section), then approved the result to be sent out this summer for its major ISO international comment ballot, which is the Committee Draft or “CD” ballot.

... At this meeting, we added several more features into C++17: ...

Competing constructors--Andrzej Krzemieński

We all got some surprises like this:

Competing constructors

By Andrzej Krzemieński

From the article:

We start with a known C++ gotcha:

std::vector<int> v (size_t(4), 2); // parentheses
std::vector<int> u {size_t(4), 2}; // braces
 
assert (v.size() == 4);
assert (u.size() == 2);
 
assert (v[0] == 2); // elements: {2, 2, 2, 2}
assert (u[0] == 4); // elements: {4, 2}

In this post I want to analyze the source of the problem a bit further, and offer some suggestions on class design.

Quick Q: Are `==` and `!=` mutually dependent?

Quick A: They are not, because it is not always true.

Recently on SO:

Are `==` and `!=` mutually dependent?

You would not want the language to automatically rewrite a != b as !(a == b) when a == b returns something other than a bool. And there are a few reasons why you might make it do that.

You may have expression builder objects, where a == b doesn't and isn't intended to perform any comparison, but simply builds some expression node representing a == b.

You may have lazy evaluation, where a == b doesn't and isn't intended to perform any comparison directly, but instead returns some kind of lazy<bool> that can be converted to bool implicitly or explicitly at some later time to actually perform the comparison. Possibly combined with the expression builder objects to allow complete expression optimisation before evaluation.

You may have some custom optional<T> template class, where given optional variables t and u, you want to allow t == u, but make it return optional<bool>.

There's probably more that I didn't think of. And even though in these examples the operation a == b and a != b do both make sense, still a != b isn't the same thing as !(a == b), so separate definitions are needed.

Typedef Literacy--Michael Park

typedef explained!

Typedef Literacy

by Michael Park

From the article:

The typedef declaration provides a way to create an alias for an existing type. For example, we can provide an alias for int called integer like so:

typedef int integer;

I imagine most people have seen such declarations, and they are fairly simple to read. In fact it’s so simple that we may incorrectly conclude that the syntax for typedef is:

typedef <existing_type> <new_type_name>;

Quick Q: Why doesn't std::queue::pop return value?

Quick A: To guarantee exception safety and for performance.

Some time ago on SO:

Why doesn't std::queue::pop return value?

So, whats the difference, pop function could have done the same thing.

It could indeed have done the same thing. The reason it didn't, is because a pop that returned the popped element is unsafe in the presence of exceptions (having to return by value and thus creating a copy).

Consider this scenario (with a naive/made up pop implementation, to ilustrate my point):

template<class T>
class queue {
    T* elements;
    std::size_t top_position;
    // stuff here
    T pop()
    {
        auto x = elements[top_position];
        // TODO: call destructor for elements[top_position] here
        --top_position;  // alter queue state here
        return x;        // calls T(const T&) which may throw
    }

If the copy constructor of T throws on return, you have already altered the state of the queue (top_position in my naive implementation) and the element is removed from the queue (and not returned). For all intents and purposes (no matter how you catch the exception in client code) the element at the top of the queue is lost.

This implementation is also inefficient in the case when you do not need the popped value (i.e. it creates a copy of the element that nobody will use).

This can be implemented safely and efficiently, with two separate operations (void pop and const T& front()).

Enabling forward traversal -- Krzysztof Ostrowski

Krzysztof Ostrowski describes in his article enabling iteration over a sequence of objects of given type without changing the type name itself.

Enabling forward traversal

by Krzysztof Ostrowski

From the article:

Let's consider following example. We have legacy interface that constructs object of type T using information stored in object of type U:

bool build_from(T& into, const U& from);

Such a build_from can be deserialiser function, e.g. from JSON to C++ type, for example:

result_type deserialise(T& into, const json_node_type& from);

Ideally, we should return into rather than taking it as an input argument, i.e. return optional<T> or type that carries information about the errors too, like C++ counterpart of Either. Unfortunately, we have to deal with legacy interafce, so that existing contracts cannot be broken, and our patch sets shall favour composition and extension over the modification.

With deserialise we know how to convert internal JSON representation into object of type T. That works fine for non-structured types. JSON offers associative containers (dictionaries, hashes, structures as defined in YAML) and collections. Dictionaries map easily to product types, struct in C++, and for those we typically need custom deserialisation procedures. Collections may be seen as abstractions over structures, or – more functionally – as sequenced values of type T for collection of type [T]. Since we know how to deserialise objects of type T, we can deserialise [T] by simply mapping deserialise over a sequence of T objects, that is doing forward traversal. Unfortunately we have just one JSON node from, not a sequence of nodes. We need to enable forward traversal for the type json_node_type with minimal number of changes.

Quick Q: Do mutexes guarantee ordering of acquisition?

Quick A: They do not.

Recently on SO:

Do mutexes guarantee ordering of acquisition?

Known problem. C++ mutexes are thin layer on top of OS-provided mutexes, and OS-provided mutexes are often not fair. They do not care for FIFO.

The other side of the same coin is that threads are usually not pre-empted until they run out of their time slice. As a result, thread A in this scenario was likely to continue to be executed, and got the mutex right away because of that.

Overload 133 is now available

ACCU’s Overload journal of April 2016 is out. It contains the following C++ related articles.

Overload 132

From the journal:

Dogen: The Package Management Saga
How do you manage packages in C++? Marco Craveiro eventually discovered Conan after some frustrating experiences. by Marco Craveiro

QM Bites – Order Your Includes (Twice Over)
Header includes can be a shambles. Matthew Wilson encourages us to bring some order to the chaos. by Matthew Wilson

A Lifetime In Python
Resource management is important in any language. Steve Love demonstrates how to use context managers in Python. by Steve Love

Deterministic Components for Distributed Systems
Non-deterministic data leads to unstable tests. Sergey Ignatchenko considers when this happens and how to avoid it. by Sergey Ignatchenko

Programming Your Own Language in C++
Scripting languages allow dynamic features easily. Vassili Kaplan writes his own in C++ allowing keywords in any human language. by Vassili Kaplan

Concepts Lite in Practice
Concepts should make templates easier to use and write. Roger Orr gives a practical example to show this. by Roger Orr

Afterwood
Magazines sometimes use the back page for adverts or summaries. Chris Oldwood has decided to provide us with his afterwords, or ‘afterwood’. by Chris Oldwood