Our website uses cookies to enhance your browsing experience.
Accept
to the top
>
>
>
History of C and C++. Part 2. Standardi…

History of C and C++. Part 2. Standardization of C and C++, Qt, Clang, and Unreal Engine

Feb 18 2025

This is a second part of the story on how the C and C++ languages came to be as we know them today. Here, we'll cover the official certification of C and C++, as well as the tools released from 1991 to the present day.

1994—POV: language development

In 1994, the C++ language creator Bjarne Stroustrup published a book on how the C++ language was created—"The Design and Evolution of C++". In this book, the author pays special attention to general design principles and the course of the language evolution from C With Classes to its current state, describing what influenced certain architectural decisions. The book also covers many language concepts essential to modern C++.

Figure N1—The first edition cover of "The Design and Evolution of C++" book

1995—Qt release

Development of the Qt library began in 1991 with the ambitious goal to create "the world's best C++ GUI implementation library". Authors wanted this project to meet the growing need for efficient and flexible GUI development tools that would integrate into C++-based platforms and enable developers to focus on application functionality.

In the early stages of the library development, authors focused on ensuring a user-friendly GUI and designing an architecture that could be easily adapted to different operating systems with minimal code changes. In 1992, the library developers introduced a paradigm based on the concepts of "signals" and "slots". This idea radically changed the approach to event handling in programming and enabled devs to streamline connection between objects in a graphical interface. Later, in 1993, this concept was implemented in code.

In the same 1993, developers implemented the first graphical core of the library and started to create visual components, which became the basis for building user interfaces.

On May 20, 1995, the Qt 0.90 library was first publicly released.

In March 2009, the first version of Qt Creator came out. It is an integrated development environment designed to streamline the work with the Qt library.

Today, Qt is one of the most comprehensive frameworks in C++. Devs actively use it in a variety of areas, including desktop and mobile application development, as well as in embedded software development.

1998—C++98

The first C++ standard, known as C++98, was released in 1998 to standardize all the features that had been added to the language since its introduction. The Annotated C++ Reference Manual highlighted the functionality that has been implemented with the release of this standard.

The use of templates has been standardized, allowing the creation of generic classes and functions that work with any data type. The use of exceptions has also been standardized.

To avoid name conflicts, namespaces were added, uniting entities such as classes, objects, and functions in a separate scope. The bool data type, as well as the true and false keywords were added to represent logical values.

The behavior of multiple inheritance and virtual functions has been standardized to ensure uniformity between compilers. The new and delete operators have also been standardized.

The standard library, particularly the standard template library, I/O thread library, complex numbers library, containers (vector, doubly linked list, set, map), adapters (stack, queue, priority queue), iterators, algorithms, function objects have also been standardized.

Same year: Boost

After the C++98 introduction, many people were unhappy with the lack of some functionality in the STL. So, a new project has appeared—Boost—a collection of class libraries that utilize C++ features and provide a high-level cross-platform interface for solving various tasks.

This project is a kind of testing ground for various language extensions and libraries that may be included in the next standard.

1998—Unreal Engine becomes real

In 1998, the 1.0 version of the Unreal Engine game engine was released. At that time, it was one of the first universal engines that combined graphics and physics engines, artificial intelligence, file and network system management, and a ready-made environment for game development.

Unreal Engine 1.0 featured some truly revolutionary technologies for the time, such as the use of a dynamic scene graph that allowed to add various effects to overlay on surfaces.

The first version of the engine was released for Windows and Macintosh platforms, but a little later it was successfully adapted for GameCube, PlayStation 2, and Xbox. Today, Unreal Engine supports most platforms: Windows, PlayStation 4 and 5, Xbox Series, Xbox One, Nintendo Switch, macOS, iOS, Android, SteamVR, Oculus, Linux, SteamDeck, and more.

A year later, an improved version of the engine, also known as Unreal Engine 1.5, was released with significant functionality enhancements. The version included: facial animation support for characters, an increased to 1024×1024 maximum texture resolution, and an extensible particle system.

1999—C99

After the first standard for the C language was adopted, it remained relatively unchanged for some time. But in 1999, the new ISO/IEC 9899:1999 standard was published.

It added some features that were previously implemented as extensions for some compilers.

The inline functions were added. When a programmer calls them, a compiler replaces the function call with the function body.

New data types appeared: long long int, additional extended integer types, the _Bool explicit logical data type, and the _Complex type to represent complex numbers.

Variable-length arrays whose length is calculated at runtime were added. Single-line comments (//) were supported both in BCPL and C++. Also, variadic macros (variable arity macros) and compound constants were added.

This standard was adopted as an ANSI standard in May 2000.

2000—CMake and cross-platform build

This build system was originally developed for the Insight Toolkit project sponsored by the U.S. National Library of Medicine (NLM). The project required support for multiple platforms. NLM has teamed Kitware with other companies and universities to develop this toolkit. They called the system CMake. It made the process of building and managing projects much easier

CMake automatically generates build files for different operating systems and compilers, which has become especially important for large projects that require versatility and flexibility. CMake soon gained widespread popularity in the software development world due to its capability to work across platforms, support complex dependencies and integrations, and provide a high degree of automation in the building process.

2005—Technical Report 1

In 2003, the C++03 standard came out. However, it didn't include many features. C++03 is a follow-up to the C++98 standard, fixing its errors and defects. During its development, many reported issues were reviewed and fixed in the standard. The only thing that has been added directly to the language since C++03 is value initialization, which executes when an object is created with an empty initializer.

However, in 2005, the Draft Technical Report on C++ Library Extensions was published, describing proposals for additions to the C++ library standard.

For example, the paper proposed:

  • the reference_wrapper class that creates a wrapper for a reference;
  • smart pointers;
  • the function, bind, result_of, and mem_fn function objects;
  • the tuple type for tuples;
  • the array type for fixed-length arrays;
  • random number generators;
  • special math functions;
  • the regex header file for working with regular expressions.

This document was published as the ISO/IEC TR 19768:2007 standard in 2007. The features it proposed found their way into the language a bit later.

2007—Clang

In 1987, the GCC compiler suite was developed under the GNU project. Originally, the GNU C Compiler supported only a compiler for C, but later support for other languages such as C++ was added. Its full name changed to the GNU Compiler Collection.

In 2007, Clang—a compiler for C-like languages based on the LLVM framework—emerged as an alternative to GCC.

One of the project goals was to implement incremental translation, enabling tighter integration between the compiler and the IDE, an area where GCC had issues. Clang modular design can be effectively used in IDEs for code indexing, syntax highlighting, and things like this.

Another major difference between Clang and GCC is their focus: the GNU Compiler Collection (GCC) prioritizes code generation, while Clang serves as a comprehensive framework for parsing, indexing, static analysis, and compilation. Additionally, during parsing, Clang preserves the original source code structure, accurately converting it into an abstract syntax tree (AST) without simplifications.

Nowadays, the project involves developers from Google and Apple, among others.

The same year: the release of Viva64, which became PVS-Studio 3 years later

On December 31, 2006 (just a few hours before 2007) the Viva64 analyzer was launched. The analyzer was designed to detect errors when migrating to 64-bit systems.

The second version of the analyzer was released in 2008. The third one, dated 2009, united Viva64 and VivaMP (a tool for analyzing issues in multithreaded programs built on OpenMP) into a single tool—PVS-Studio.

Today, PVS-Studio is a static analyzer and SAST solution for C, C++, C#, and Java. You can try the tool at this link.

2011—C++11

A new version of the C++ language standard was released in 2011. It introduced changes to the language core, an extended standard library, which included all of the TR1 proposals except for special math functions.

Multithreading support was added to the core, along with improvements to generic programming, unified initialization, and overall performance enhancements. For example, move semantics appeared—a set of semantic rules and C++ tools designed to move objects whose lifetime is about to expire instead of copying them, which helps avoid costly duplication. To enable it, rvalue and forwarding references were introduced, along with move constructors and the move assignment operator. Additionally, the standard template library was updated with functions to support move semantics, such as std::move and std::forward.

The auto placeholder type specifiers appeared in this standard, indicating that the type of the declared variable will be automatically derived from its initializer. The decltype specifier also appeared. It outputs the type of the declared entity or the type and category of the passed expression value.

The update introduced the capability to declare functions as deleted using = delete; and instruct the compiler to automatically generate special function bodies using = default;. Lambda expressions appeared in the language.

New specifiers—final and override—were introduced for class and virtual function declarations. Both force the compiler to check whether any virtual function from the base class is overridden. This gets rid of a frequent error in C++, when instead of overriding a virtual function from the base class, a programmer actually hides it by adding a new function. Also, the first specifier can be additionally applied to the class definition, to prevent inheritance from such a class.

The std::nullptr_t type and the nullptr literal of this type were added. With the literal, a developer can set the pointer state to null instead of using the NULL macro. It also helps avoid ambiguity in function calls when there are two overloads with an integral type and a pointer. A similar literal later appeared in C, but only with the C23 standard.

The constexpr specifier also appeared. It allows to move the evaluation of the function value to the compilation stage, and further to use it where only constant compile-time expressions are allowed. I recommend reading this article that covers the design and evolution of constexpr in C++.

A range-based for loop was added. It enables a developer to iterate over an object (such as a standard container or a user-defined type), provided that the begin and end member functions are defined for the type. These functions should return iterators to the first element and to the element following the last element. This feature was added from the Boost.Foreach library. The static_assert (Boost.StaticAssert) keyword was also added from the library, allowing assertions to be checked at compile time.

There have also been changes to the standard library. For example, here's what was added:

  • unordered associative containers: std::unordered_set, std::unordered_map and their multi-versions;
  • sequence containers: std:array and std::forward_list;
  • smart pointers: std::unique_ptr, std::shared_ptr, std::weak_ptr;
  • features for working with random numbers: various generators (std:: linear_congruential_engine, std::mersenne_twister_engine, std:: subtract_with_carry_engine), adapters (std: :discard_block_engine, std:: independent_bits_engine, std:: shuffle_order_engine), and distribution functions (uniform, normal, Poisson, Bernoulli);
  • features for multithreaded programming: std::thread, std::mutex, std::lock_guard, std::unique_lock, std::condition_variable, std::future, std::promise, ....
  • and others.

Note. We recently posted an article on why std:array in C++ is not slower than an array in C. You can read it here.

2014—C++14

On August 18, 2014, the C++14 standard was released, intended as an extension to the previous standard, C++11. Although this standard is considered a minor one, the list of changes is not as small as it may seem.

There are several reasons for this. Firstly, this standard polished C++11 and fixed various defects (a total of 276 core and 158 library defects). Secondly, variable templates were added to enable the definition of a variable family or static data members. Additionally, features that are essential for writing C++ code today were introduced, for example:

  • full-featured auto output for return function types;
  • generic lambdas;
  • decltype(auto);
  • relaxed restrictions on the contents of constexpr functions, allowing almost any code to be evaluated at compile time;
  • etc.

Here comes the C++14 killer feature: it became possible to eliminate or merge some dynamic allocations. In the first case, the compiler can now provide a buffer without calling a replaceable allocation function, for example, by allocating it on the stack. In the second case, when the new e1 expression is evaluated, the compiler can allocate memory for another new e2 expression as well. This optimization is possible if the following conditions are met:

  • the lifetime of the object allocated by e1 strictly contains the lifetime of the object allocated by e2.
  • e1 and e2 must call the same replaceable global allocation function;
  • when the replaceable allocation function that throws an exception is called, exceptions in e1 and e2 will be caught by the same handler.

2017—C++17

A new standard came out in December 2017. Let's go through the features of the updated standard.

Fold expressions appeared. A fold expression is a C++ syntax element designed to fold packs of variadic template parameters using an optional initial value. It helps avoid cumbersome recursive calls and allows to apply operations to all individual pack arguments in a concise manner. Also, auto for non-type template parameters was added.

The if and switch constructs with initializers were added. Another significant addition was if constexpr, which enables compile-time branching, reducing the need for SFINAE-heavy code. The constexpr functions were also improved to support lambda expressions and declare them as constexpr. The *this lambda capture was introduced, which copies the state of the current object.

A mechanism of structured binding appeared, enabling convenient decomposition of pairs, tuples, and other similar objects.

Changes to the standard also affected the standard library. New types, tools for memory management, and compile-time programming were added to it.

Note. In 2017, when the standard was released, we published an article with a detailed breakdown of new C++17 features. You can read it here.

2020—C++20

In December 2020, after another three-year cycle, the C++20 standard was released.

C++ 20 introduced constraints that enable developers to define requirements for template arguments. The named sets of constraints were called concepts. Constraint violations are found at the compilation stage, which makes error detection quite easy.

The language introduced modules that allowed declaration and definition exchanges between translation units. Coroutines—functions that can stop execution to resume it later—were also added.

The spaceship-operator (<=>) appeared, which allowed to transfer data member comparison to the compiler. The implementation of this feature resulted in the non-type template parameter for custom types.

Some features were allowed for constexpr, such as calling virtual functions or using dynamic_cast. The consteval and constinit specifiers also appeared. The first specifies that each function call should create a compile-time constant. The second indicates that the variable is initialized with a static storage duration or thread storage duration compile-time constant. It can be modified later, unlike constexpr.

The constexpr allocators appeared, allowing even containers requiring memory allocation to be used within the constexpr range. However, dynamic allocation cannot leave the constexpr function.

Functionality check macros were added. Their function is to provide a simple and portable way to test the language features introduced since the C++11 standard.

Starting with C++20, range-based for loops got support for pre-initialization, and lambda expressions were enhanced with batch extensions to lambda capture.

2024—Our days: C++23

C++23 came out last October. The process of developing this standard differed from previous ones because almost all committee meetings were held remotely.

This standard introduced explicit object member functions. All non-static functions in classes always take an additional parameter, which is the object itself (the this pointer). Before C++23, the function used to implicitly take it, but in the new standard enables to explicitly specify this parameter when declaring a function.

To optimize compilation time, if consteval was added to check weather a function is executed in a constant context.

Lambda expressions got attribute support, and multidimensional arrays appeared for multidimensional arrays.

It became possible to mark unreachable code using std:unreachable, helping compiler optimization.

String formatting has been improved in the standard library, and new std::flat_map and std::flat_set adapters have been added.

Same year: C23

You may have noticed that no standard for C after C99 was described in this article. Why? All language standards that followed were focused on refining the language features that have been already introduced, as well as on additions to the standard library.

The most notable language features came out with the C11 standard, as it has undergone some changes. For example, multithreading support and type-generic expressions using the _Generic keyword.

Along with C++23, C23 was also released in 2024. This standard removed the function definition format from K&R. It had a major drawback—the compiler couldn't check argument type compatibility when calling functions. This change resulted in more similarities between C and C++.

In addition, the language got some features that were previously added to C++:

  • static_assert as a keyword instead of _Static_assert introduced in C11;
  • thread_local as a keyword instead of the macro expanded as _Thread_local;
  • the bool type with pre-specified true and false values;
  • type output via auto;
  • the realloc behavior is now undefined when the allocation size is 0;
  • new floating-point types;
  • fixed-width integral types;
  • nullptr and nullptr_t.

The #embed directive also appeared, enabling the easy inclusion of binary data in an executable program image without an external script.

Conclusion

Here, our time travel comes to an end, and we are back in the present. C and C++ are truly iconic languages that, despite their age, remain at the top of the most popular programming languages list to this day. I hope you too found this journey through history fascinating.

Posts: articles

Poll:

Subscribe
and get the e-book
for free!

book terrible tips


Comments (0)

Next comments next comments
close comment form
close form

Fill out the form in 2 simple steps below:

Your contact information:

Step 1
Congratulations! This is your promo code!

Desired license type:

Step 2
Team license
Enterprise license
** By clicking this button you agree to our Privacy Policy statement
close form
Request our prices
New License
License Renewal
--Select currency--
USD
EUR
* By clicking this button you agree to our Privacy Policy statement

close form
Free PVS‑Studio license for Microsoft MVP specialists
* By clicking this button you agree to our Privacy Policy statement

close form
To get the licence for your open-source project, please fill out this form
* By clicking this button you agree to our Privacy Policy statement

close form
I am interested to try it on the platforms:
* By clicking this button you agree to our Privacy Policy statement

close form
check circle
Message submitted.

Your message has been sent. We will email you at


If you do not see the email in your inbox, please check if it is filtered to one of the following folders:

  • Promotion
  • Updates
  • Spam