Articles & Books

Breaking Down C++20 Callable Concepts -- John Farrier

Learn about C++20's Callable Concepts, how they improve on SFINAE, and how to use them in your own code.

Breaking Down C++20 Callable Concepts

By John Farrier

From the article:

C++20 Callable Concepts refer to a powerful feature introduced in the C++20 standard that allows developers to specify and enforce constraints on function objects, lambdas, and other callable entities in a more expressive and type-safe manner. Callable Concepts enable the compiler to check if a given callable meets specific requirements, such as having certain member functions or satisfying particular type traits, before allowing it to be used in a template or function. This helps improve code readability, maintainability, and error detection, as it provides clearer and more structured ways to define the expected behavior and capabilities of callables in C++ code.

 

Easily Protect Your C++ Code Against Integer Overflow With SafeInt -- by Giovanni Dicanio

Integer overflows can be hidden inside your C++ code and can cause subtle nasty bugs.

Fortunately, it's easy to guard your code against those subtle bugs, thanks to an open-source easy-to-use library:

Protecting Your C++ Code Against Integer Overflow Made Easy by SafeInt

by Giovanni Dicanio

From the article:

In previous blog posts I discussed the problem of integer overflow and some subtle bugs that can be caused by that. (...)

Of course, writing this kind of complicated check code each time there is a sum operation that could potentially overflow would be excruciatingly cumbersome, and bug prone! (...)

Fortunately, you don’t have to do all that work! In fact, there is an open source library that does exactly that! This library is called SafeInt. (...)

The code will still look nice and simple, but safety checks will happen automatically under the hood. Thank you very much SafeInt and C++ operator overloading!

 

When an Empty Destructor is Required -- Andreas Fertig

me.pngIn my previous post, "Why you shouldn't provide an empty destructor," we discussed the importance of not providing an empty destructor in most cases. However, in this post, we'll explore a rare exception to this rule that arises when using the PImpl idiom to hide implementation details, specifically in situations where the unique_ptr encounters issues with incomplete types. Let's delve into this exception and learn when it's necessary to provide an empty destructor.

When an Empty Destructor is Required

by Andreas Fertig

From the article:

As you probably know from life, not only programming. There is no rule without an exception. Let's talk about the one case that requires an empty destructor (yes, I know it sounds silly). Suppose you have the following code:

In file included from <source>:2:
In file included from /opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/memory:76:
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/unique_ptr.h:93:16: error: invalid application of 'sizeof' to an incomplete type 'Orange'
        static_assert(sizeof(_Tp)>0,
                      ^~~~~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/lib/gcc/x86_64-linux-gnu/12.2.0/../../../../include/c++/12.2.0/bits/unique_ptr.h:396:4: note: in instantiation of member function 'std::default_delete<Orange>::operator()' requested here
          get_deleter()(std::move(__ptr));
          ^
<source>:4:7: note: in instantiation of member function 'std::unique_ptr<Orange>::~unique_ptr' requested here
class Apple
      ^
<source>:6:27: note: forward declaration of 'Orange'
    std::unique_ptr<class Orange> mOrange{};
                          ^
1 error generated.
Compiler returned: 1
 
Essentially, this message tells you that the std::unique_ptr cannot instantiate the required destructor for itself typed with Orange. The simple reason is that, at this point, Orange has no visible destructor. Which is the entire point of the PImpl idiom. What now?

Boost 1.84.0 has been released

space.pngspace.pnggetboost.pngRelease 1.84.0 of the Boost C++ Libraries is now available.

These open-source libraries work well with the C++ Standard Library, and are usable across a broad spectrum of applications. The Boost license encourages both commercial and non-commercial use.

Release 1.84.0 contains two new libraries and numerous enhancements and bug fixes for existing libraries.

New Libraries

  • Cobalt: Basic algorithms and types for C++20 coroutines, from Klemens Morgenstern.
  • Redis: Redis async client library built on top of Boost.Asio, from Marcelo Zimbres Silva.

Here are some useful links for 1.84.0.


Marshall Clow and Glen Fernandes managed this release - we very much appreciate their continued hard work!

C++20, Spans, Threads and Fun -- Bartlomiej Filipek

C++20_Spans_Threads_and_Fun.pngIn this post, we’ll have fun using C++20’s spans to process data on multiple threads. What’s more, we’ll be equipped with the latest concurrency features from C++20.

C++20, Spans, Threads and Fun

by Bartlomiej Filipek

From the article:

Our task is relatively simple but can be extended to various multi-phase computations.

We need to initialize a container with numbers, filter them, then build a histogram.

Here’s the overview of the process:

CLion Nova Explodes onto the C and C++ Development Scene -- Anastasia Kazakova

clionnova.pngWe’re announcing a free early preview of CLion, which uses the ReSharper C++/Rider C++ language engine instead of the CLion "legacy" engine. The Preview build is available via our dedicated Toolbox App feed. At some point in 2024, depending on the results of the feedback collected, CLion Nova will be merged into CLion. Until then, the Preview build will be free to use and can be installed in parallel with your usual CLion (Classic) installation.

CLion Nova Explodes onto the C and C++ Development Scene

by Anastasia Kazakova

From the article:

The first C++ engine by JetBrains was designed for AppCode, our IDE for iOS and macOS developers. It was part of the IntelliJ Platform, initially written in Java and later also in Kotlin. The approach and the architecture of the engine serve many languages in IntelliJ-based IDEs well; however, this design turned out not to be the best fit for the C++ language specifically.

To more quickly align with the evolution of C++ and to separate the engine and IDE processes, a clangd-based engine was later added to CLion. Built on our custom branch of clangd, this engine detects any warnings and errors, shows them in the editor, and suggests quick-fixes, as well as performing highlighting, completion, and certain navigation actions. It’s also used for things like data flow analysis and MISRA checks. Meanwhile, CLion’s “legacy” engine is responsible for other code insight features like refactorings. You can see a detailed “list of responsibilities” in our CLion documentation.

How Can I Prevent Myself From Using a Parameter After I’ve Extracted All Value? -- Raymond Chen

Imagine you have a function parameter that you want to protect from direct access, ensuring that all future interactions occur through a wrapper or transformation. This situation often arises in scenarios like implementing a logging wrapper for a class. In this discussion, we'll explore a clever technique known as "hide_name" to achieve this goal, allowing you to enforce the use of the wrapper and prevent direct access to the parameter.

How Can I Prevent Myself From Using a Parameter After I’ve Extracted All Value From It?

By Raymond Chen

From the article:

Suppose you have a function that takes a parameter that you want to transform in some way, and you want to require that all future access to the parameter be done through the transformed version. One example is a wrapper class that does logging.¹

struct WidgetRefWrapper
{
    WidgetRefWrapper(
        Widget& widget,
        Logger& logger) :
    m_widget(widget), m_logger(logger) {}
    
    void Toggle() try
    {
        m_logger.Log("Toggling the widget");
        m_widget.Toggle();
        m_logger.Log("Toggled the widget");
    } catch (...) {
        m_logger.Log("Exception while toggling the widget");
        throw;
    }

private:
    Widget& m_widget;
    Logger& m_logger;
};

void DoSomething(Widget& widget)
{
    Logger& logger = GetCurrentLogger();
    WidgetWrapper wrapper(widget, logger);

    // Do not use the widget directly!
    // Always use the wrapper!

    if (needs_toggling) {
        wrapper.Toggle();
    }
}

You want that “Do not use the widget directly!” comment to have some teeth. Can you “poison” the widget parameter so it cannot be used any more?