Articles & Books

Type Safe C++ enum Extensions -- Alf Steinbach

steinbach1.jpgIs it possible to extend a value type in C++? Alf Steinbach describes how to extend enum values.

Type Safe C++ enum Extensions

by Alf Steinbach

From the article:

Consider if an enum like the following,

  enum class Suit{
  spades, hearts, diamonds, clubs };

could be extended like

  enum class Suit_with_joker extends Suit {
    joker };

where

  • Suit_with_joker has all the enumerators of Suit plus the joker enumerator; and
  • enumerators introduced in Suit_with_joker get integer values following those of Suit; and
  • any Suit value is also a Suit_with_joker value.

This would be an example of what I’ll call a value type extension.

The apparently backwards is-a relationship in the last point, where any value of the original type is-a value of the derived type, is characteristic of value type extensions.

C++20 totally lacks support for value type extensions, of enum types or other types.

It’s Great That You Provide Operator Overloads, But It’s Also Nice to Have Names -- Raymond Chen

RaymondChenPic.pngOperator overloading. Looks great. Reduces verbosity. Until it doesn’t.

It’s Great That You Provide Operator Overloads, But It’s Also Nice to Have Names

by Raymond Chen

From the article:

Consider this overloaded function call operator:

struct StorageLoader
{
    template<DataType>
    DataType operator()(StorageOptions<DataType> const* options);
};

The idea is that you can use the function call operator on a Storage­Loader object to load data from storage, using a StorageOptions to describe how you want it to be loaded.

 

Object Lifetime -- Ilya Doroshenko

Today, we are going to talk about an object. Without further ado, let’s dive deeper!

Object Lifetime

by Ilya Doroshenko

From the article:

What is an object? According to the C++ standard, part 3.9.8 under the name of [basic.types]

 An object type is a (possibly cv-qualified) type that is not a function type, not a reference type, and not a void type.

Now is int i an object? Yes.

Is void* p an object? Still yes, because pointers are types themselves, they are not references.

As we said, references are not types, but what if we declare something like struct S{ int& ref;}; would that be an object type? 

 

Dealing with Mutation: Guarded Suspension -- Rainer Grimm

dealingwithmutation.pngGuarded Suspension applies a unique strategy to deal with mutation. It signals when it is done with its modification.

Dealing with Mutation: Guarded Suspension

by Rainer Grimm

From the article:

The guarded suspension basic variant combines a lock and a precondition that must be satisfied. If the precondition is not fulfilled, that checking thread puts itself to sleep. The checking thread uses a lock to avoid a race condition that may result in a data race or a deadlock.

Various variants of the Guarded Suspension exist:

  • The waiting thread can passively be notified about the state change or actively ask for the state change. In short, I call this push versus pull principle.
  • The waiting can be done with or without a time boundary.
  • The notification can be sent to one or all waiting threads.

I present in this post only the rough idea. Let me start with the push principle.

You often synchronize threads with a condition variable or a future/promise pair. The condition variable or the promise sends the notification to the waiting thread. A promise has no notify_one or notify_all member function. Typically, a valueless set_value call is used to ...

C++17’s Useful Features for Embedded Systems -- Çağlayan Dökme

caglayan.pngRecently, our team at Meteksan Defense is upgrading its development environment to use newer versions of many tools and programming languages. One of the more difficult transitions has been the upgrade of our C++11 code base to C++17 for our embedded applications.

In this article, I will be showing some features of C++17 that can also be helpful in the embedded world.

C++17’s Useful Features for Embedded Systems

by Çağlayan Dökme

From the article:

C++14 had smaller upgrades compared to the ones we saw when migrating to C++11 from C++03. Hence, there are only a few features in C++14 that you can use in an embedded system.

Binary Literals

If you are frequently dealing with bitwise operations and modifying registers, you will love these literals. Some compilers had extensions that support such literals, but now they have a place in the actual standard.

uint8_t a = 0b110; // == 6 
uint8_t b = 0b1111'1111; // == 255 

Constraint relaxed constexpr**

With C++14, the syntax you can use in a constexpr function is expanded. Check out this post on StackOverflow. The constexpr is beneficial in the embedded world since...

On Writing Functions That Accept Any Specialization of a C++ Template Type -- Raymond Chen

RaymondChenPic.pngSuppose you want to write a template function that accepts any specialization of std::vector? What may work today may not work tomorrow.

On Writing Functions That Accept Any Specialization of a C++ Template Type

by Raymond Chen

From the article:

Suppose you want to write a template function that accepts any specialization of std::vector. Your first try would probably be something like this:

template<typename Value>
void accept_any_vector(std::vector<Value> v);

However, this does not actually accept any vector specialization. There is a second template argument for the allocator, which has a default value that nearly everyone uses. But if somebody has a vector with a custom allocator, then your function won’t match.

Dealing with Mutation: Thread-Safe Interface -- Rainer Grimm

dealingwithmutations.pngI continue my journey with concurrency patterns in today's post. The Thread-Safe Interface fits very well when the critical sections are just objects.

Dealing with Mutation: Thread-Safe Interface

by Rainer Grimm

From the article:

The naive idea to protect all member functions of a class with a lock causes, in the best case, a performance issue and, in the worst case, a deadlock.

A Deadlock

The small code snippet has a deadlock.

struct Critical{
    void memberFunction1(){
        lock(mut);
        memberFunction2();
    ...
}

void memberFunction2(){
        lock(mut);
        ...
    }

    mutex mut;
};

Critical crit;
crit.memberFunction1();

Calling crit.memberFunction1 causes the mutex mut to be locked twice. For simplicity reasons, the lock is a scoped lock. Here are the two issues:

60 terrible tips for a C++ developer

In this article, you're going to find 60 terrible coding tips — and explanations of why they are terrible. It's a fun and serious piece at the same time. No matter how terrible these tips look, they aren't fiction, they are real: we saw them all in the real programming world.

60 terrible tips for a C++ developer

by Andrey Karpov

From the article:

Terrible tip N46. Write your code as if the chairman of the IOCCC judges will read it and as if they know where you live (to come and give you the prize).

It's a reference to a quote — "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live". This is John F. Woods's phrase, however, it's sometimes credited to Steve McConnell who quoted it in his "Code Complete" book.

Into the Extreme – Fold-Expressions -- Coral Kashri

CoralKashri.pngFold expressions exist in C++ since C++17 and significantly affect how we treat variadic templates. Back in the day, I wrote about fold-expressions as part of the metaprogramming series, but today we will explore the extreme cases of fold-expression usages.

Into the Extreme – Fold-Expressions

by Coral Kashri

From the article:

In the case of a unary fold (fold expression without initialization), this case is legal for 3 types of operators: &&||, and ,.

Operator &&

template <typename ...Args>
auto and_cond(Args... args) {
    return (args && ...);
}

In case of empty parameters (for the call and_cond()), the function will return true. A reasonable explanation for this decision might be that && operator requires there won’t be any part that evaluates false. In this case, there are no parts at all, so none of the parts evaluates false, and therefore the result should be...

Dealing with Mutation: Locking -- Rainer Grimm

dealingwithmutationlocking.pngLocking is a straightforward idea to protect a critical section. A critical section is a section of code that, at most, one thread can use at any time.

Dealing with Mutation: Locking

by Rainer Grimm

From the article:

Scoped locking is the idea of RAII applied to a mutex. Scoped locking is also known as synchronized block and guard. The key idea of this idiom is to bind the resource acquisition and release to an object’s lifetime. As the name suggests, the lifetime of the object is scoped. Scoped means that the C++ run time is responsible for object destruction and, therefore, for releasing the resource.

The class ScopedLock implements Scoped Locking.