C++09 Attributes: Specify Your Constructs’ Unusual Properties

C++09 Attributes: Specify Your Constructs’ Unusual Properties

++ constructs such as functions, types, variables, and blocks are associated with implicit properties that you sometimes need to override. Certain constructs require you to specify their unusual properties, for example:

  • A function that never returns
  • A type with a particular alignment restriction
  • A virtual function that must not be overridden

Attributes, a new C++09 feature, are compile-time tokens that enable you to designate properties like these. By using attributes, you can specify additional information about your programming constructs conveniently and portably. This 10-Minute Solution shows how to apply this technique.

You need to tell the compiler and your fellow programmers how to use a certain component, but you don’t want to use nonstandard features or risk inadvertent usage violations.

Use C++09 attributes.

final, Finally

Before the advent of C++09, ensuring that clients could not override a certain virtual function any further was a struggle. Consider the following example:

struct B { virtual void f (); //do not override this!};struct D : B { void f(); //overriding B::f, uncaught by the compiler};

The author of class B made her intentions clear: Any class derived from B must not override f(). Still, an innocent user who derived D from Bmistakenly violated this requirement. A standard C++ compiler cannot detect this violation because all public virtual functions can be overridden by default.

C++09 attributes tackle this problem. An attribute is a token enclosed between double square brackets, for example [[myattribute]]. C++09 defines several attribute tokens, which you need to understand aren’t reserved keywords. To indicate that a virtual function must not be overridden any further, you need to appertain the attribute [[final]]to the last permitted override of that function:

struct B //C++09 only { virtual void f [[final]] ();//can't override f() any further!};struct D : B { void f(); // compilation error: attempt to override B::f};

The [[final]] attribute applies to class definitions and to virtual member functions declared in a class definition. If the [[final]] attribute is specified for a class definition, it’s equivalent to being specified for each virtual member function of that class, including inherited member functions. The following declaration of class A

struct A [[final]] //C++09 only{ virtual void f(); virtual void g(); virtual void h();};

…is equivalent to:

struct A  //C++09 only{ virtual void f [[final]] (); virtual void g [[final]] (); virtual void h [[final]] ();};

The Point of noreturn

Certain functions can exhibit some unusual behavior. For instance, functions that never return to their caller are rather common in applications that use signals and exceptions. Additionally, some odd beasts such as the POSIX fork()function have the unusual property of returning not once per invocation but twice: once in the parent and once in the child.

Programmers need to be alerted of such unusual behavior when they encounter these functions. Furthermore, compilers often issue a warning when they detect a function call that never returns. Once again, C++09 attributes come to rescue, making your code easier to understand and more secure.

To designate a function that never returns, use the attribute-token noreturn and make sure the first declaration of the function specifies the noreturn attribute. If you declare a function with the noreturn attribute in one translation unit and then declare it without the noreturnattribute in another translation unit, your program will be ill formed.

Here’s an example of a noreturnfunction:

void f [[ noreturn ]] () { throw "failed"; // OK}

GCC users may recognize the [[noreturn]] attribute as the equivalent of __noreturn__:

//GCC specific void die(int, void *) __attribute__((__noreturn__)); //GCC

In C++09, you would declare the same function like this:

void die [[ noreturn ]] (int, void *); //C++09

Alignment Revisited

In a previous 10-Minute Solution, I showed how to probe and override the alignment of types and objects. Newsflash: The latest C++09 standard got rid of the alignas keyword (but the alignofoperator remains in the standard).

If you want to override the default alignment of a type or an object, or you want to ensure that the same alignment is used in every environment, use the [[align]] attribute. The align token takes a type or an assignment expression as its argument. (Certain attributes can have an argument clause enclosed in parentheses.) For example, here’s how you declare a char array that is suitably aligned for double:

//byte array suitably aligned for doubleunsigned char c [[align(double)]] [sizeof(double)];

When multiple alignment attributes are specified for an object, the alignment requirement is set to the strictest (highest) specified attribute. Here is how you would declare a buffer with an alignment requirement of A, holding N elements of type T:

//choose the strictest alignment of the two T buffer [[align(T),align(A)]] [N];

Tribute to Attributes

Presently, C++09 defines four attribute tokens. Although I don’t discuss the details in this article, the fourth token, carries_dependency, specifies dependency propagation into and out of functions. The standard allows implementations to extend the token system by defining compiler-specific attribute tokens. Thus, a hypothetical POSIX compiler may define an attribute token [[returns_twice]], which appertains to the fork()function as follows:

pid_t  fork [[returns_twice]] (void);

Look for a deeper examination of the carries_dependencytoken in an upcoming 10-Minute Solution. In the meantime, use attributes to alert the compiler and your fellow programmers to the unusual behavior of some of your programming constructs.

Share the Post:
XDR solutions

The Benefits of Using XDR Solutions

Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved

AI is revolutionizing fraud detection

How AI is Revolutionizing Fraud Detection

Artificial intelligence – commonly known as AI – means a form of technology with multiple uses. As a result, it has become extremely valuable to a number of businesses across

AI innovation

Companies Leading AI Innovation in 2023

Artificial intelligence (AI) has been transforming industries and revolutionizing business operations. AI’s potential to enhance efficiency and productivity has become crucial to many businesses. As we move into 2023, several

data fivetran pricing

Fivetran Pricing Explained

One of the biggest trends of the 21st century is the massive surge in analytics. Analytics is the process of utilizing data to drive future decision-making. With so much of

kubernetes logging

Kubernetes Logging: What You Need to Know

Kubernetes from Google is one of the most popular open-source and free container management solutions made to make managing and deploying applications easier. It has a solid architecture that makes

ransomware cyber attack

Why Is Ransomware Such a Major Threat?

One of the most significant cyber threats faced by modern organizations is a ransomware attack. Ransomware attacks have grown in both sophistication and frequency over the past few years, forcing

data dictionary

Tools You Need to Make a Data Dictionary

Data dictionaries are crucial for organizations of all sizes that deal with large amounts of data. they are centralized repositories of all the data in organizations, including metadata such as