Category Archives: C++

An example of how GCC 13 optimizes std::memcpy

C++ code below demonstrates how GCC 13 optimizes std::memcpy and a temporary std::array:

#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <new>
#include <type_traits>

template <class T>
T* startLifetimeAs(void* const buffer)
{
    std::array<std::byte, sizeof(T)> representation;

    // Preserve the bytes before placement new ends the previous lifetime.
    std::memcpy(representation.data(), buffer, representation.size());

    // Start the lifetime of T in the original storage.
    T* const result = ::new (buffer) T;

    // Initialize the object representation of the newly created T.
    std::memcpy(result, representation.data(), representation.size());

    return result;
}
(more…)

How Placement New Ends an Object’s Lifetime

Below I provided an example demonstrating how placement new creates multiple objects within the same byte storage. Non-overlapping objects can coexist, while constructing an overlapping object ends the lifetime of the previously existing object. Accessing an object after its lifetime has ended causes undefined behavior.

#include <cstddef>
#include <cstdint>
#include <iostream>
#include <new>

struct Packet final
{
    std::uint64_t Data[4];
};

struct A final
{
    std::uint32_t First;
    std::uint32_t Second;
};

struct B final
{
    std::uint32_t First;
    std::uint32_t Second;
};

struct C final
{
    std::uint32_t Value;
};
(more…)

Examples of Undefined Behavior Related to Type Accessibility in C++

From C++ standard:

Attempting to read or modify the stored value through any other type results in undefined behavior.

Any other type means type accessablity:

The first basic example illustrating this principle:

#include <cstdint>

std::uint32_t toInt(float value)
{
    auto* p = reinterpret_cast<std::uint32_t*>(&value); // The cast itself is permitted.
    return *p; // Undefined behavior: accesses a float object through a std::uint32_t glvalue.
}
(more…)

Violating strict aliasing with reinterpret_cast in C++

The first simple example:

#include <bit>
#include <cstdint>
#include <iomanip>
#include <iostream>

std::uint32_t badBits(const float value)
{
  // const prevents writes, but reading a float through a uint32_t pointer
  // still violates the strict-aliasing rule.
  const auto* bits = reinterpret_cast<const std::uint32_t*>(&value);
  return *bits; // Undefined behavior.
}

std::uint32_t goodBits(const float value)
{
  // std::bit_cast copies the object representation without violating
  // strict-aliasing or object-lifetime rules.
  return std::bit_cast<std::uint32_t>(value);
}

int main()
{
  constexpr float value = 1.0F;

  std::cout << std::hex
      << "bad:  0x" << badBits(value) << '\n'
      << "good: 0x" << goodBits(value) << '\n';
}
(more…)

Override one virtual function multiple times in C++

The code below does not compile in C++:

template <class Result, class... Params>
class Slot
{
public:

    virtual Result operator()(Params ... args) = 0;
};
(more…)

Why do we pass parameters to coroutines by value in C++?

C++ coroutines and const reference parameters

A coroutine func accepts a parameter by const reference in the code below:

#include <boost/asio.hpp>

#include <iostream>

namespace asio = boost::asio;
using asio::awaitable;
using asio::use_awaitable;

class Param
{
public:

    Param(int val) : m_val(val)
    {
        std::cout << "Param constructor " << m_val << std::endl;
    }
(more…)

An example where we need const_cast in C++

class Example
{
public:

    Example()
    {
        m.emplace("abc", 13);
    }

    const int& findValue(const std::string& val) const
    {
        auto i = m.find(val);

        if (i == m.end()) {
            throw std::runtime_error(std::format("Key {} not found.", val));
        }

        return i->second;
    }

    int& findValue(const std::string& val)
    {
        return const_cast<int&>(
            const_cast<const Example*>(this)->findValue(val));
    }
(more…)

An Interface Segregation Principle (ISP) example

#include <iostream>
#include <memory>
#include <string>
#include <vector>

struct IObject {
    virtual ~IObject() = default;

    /// Returns the name of the object.
    virtual std::string getName() const = 0;

    /// Prints a textual description of the object.
    virtual void describe() const = 0;

    /// Eats another object.
    virtual bool eat(IObject* other) = 0;
};
(more…)

An investigation of why dynamic_cast violates LSP

Signal sender cast in QT

QT implies that the client code will do qobject_cast that is actually dynamic_cast:

awl::ProcessTask<void> MarketModel::coPlaceOrder(OrderPtr p)
{
    // Update SQLite databse...
    // ...
    // QT signals are used in both C++ and QML.
    // They works with QObject*, and they are not aware of concrete types.
    QObject::connect(p.get(), &OrderModel::statusChanged, this, &MarketModel::onOrderStatusChanged);
}
(more…)

Examples of const function parameters in C++

Examples with int

Compiles without warnings with MSVC:

class A
{
public:

    void f(const int a);
};

void A::f(int a)
{
    a = 10;
    std::cout << a;
}
(more…)