std::vector

std::vector is a dynamic container that can be used with offsets. Unlike static arrays, it can grow and shrink in size at runtime, but you can use offsets as well as iterators to navigate on them.

Some key points about std::vector

  • Dynamic resizing: When you add elements to a std::vector, it can automatically resize itself to accommodate the new elements.
  • Random access: You can access any element of a std::vector using its index, just like a regular array.
  • Efficient insertion and deletion: Inserting or deleting elements at the end of a std::vector is very efficient.
  • Memory management: std::vector handles memory management for you, so you don’t have to worry about allocating and deallocating memory manually.
  • Iterators: std::vector provides iterators that allow you to iterate over its elements in a convenient way.

Example of std:vector in C++

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers;

    // Add elements to the vector
    numbers.push_back(1);
    numbers.push_back(2);
    numbers.push_back(3);   


    // Access elements using   
 their indices
    std::cout << numbers[0] << std::endl;
    std::cout << numbers[1] << std::endl;
    std::cout << numbers[2] << std::endl;

    // Iterate over the elements using a for loop
    for (int number : numbers) {
        std::cout << number << std::endl;
    }

    return 0;
}

It will output 1,2,3 and 1,2,3.

Differences between std::vector and std::list

Featurestd::vectorstd::list
Underlying data structureDynamic arrayDoubly linked list
Random accessYesNo
Insertion/deletion at the beginning/middleInefficient (O(n))Efficient (O(1))
Insertion/deletion at the endEfficient (O(1))Efficient (O(1))
IteratorsRandom access iteratorsBidirectional iterators
Memory usageGenerally more compactGenerally less compact (due to pointers)
Export to Sheets

std::vector is often preferred due to random access and memory efficiency, while std::list if the choice if you often need to insert at the beginning or in the middle.

std::erase, erase_if C++20

In this blog post, we’ll explore how std::erase functions simplify container manipulation and improve code readability.

Dealing with the removal of specific elements from a container in your C++ code can often be a cumbersome and error-prone task. Fortunately, C++20 introduces two powerful allies to streamline this process: std::erase and std::erase_if. These functions bring efficiency and clarity to element removal, and in this article, we’ll explore their workings and benefits.

Why We Need Easy Element Removal

When you’re working with C++ containers like vectors or lists, you often want to kick out some elements based on certain conditions or values. Before C++20, this was like navigating a maze blindfolded. You had to write loops and custom code to find and remove the elements you wanted. Not exactly a picnic, right?

Meet std::erase: The Element Eraser

std::erase is like the Marie Kondo of C++20. It helps you tidy up your container by removing all instances of a specific value. It’s super easy to use and works with various container types—vectors, lists, and even sets and maps. Here’s how it works:

cppCopy code

std::vector<int> numbers = {1, 2, 3, 2, 4, 2, 5}; std::erase(numbers, 2);  // Say goodbye to all those 2s

In this example, we’re saying, “Hey, std::erase, please get rid of all the 2s.” And just like magic, the vector becomes {1, 3, 4, 5}. Neat, right?

Meet std::erase_if: The Selective Element Picker

Now, what if you want to get a bit pickier and remove elements based on custom conditions? That’s where std::erase_if comes in. It’s like having a personal assistant that follows your criteria. Check it out:

cppCopy code

std::vector<int> numbers = {1, 2, 3, 4, 5, 6}; std::erase_if(numbers, [](int n) { returnn % 2 == 0; });  // Adios, even numbers!

In this case, we’re using a cool lambda function as a “picker.” It says, “Bye-bye, even numbers,” and, voilà, we’re left with {1, 3, 5}. std::erase_if lets you customize the removal process based on your whims and fancies.

The Perks of std::erase and std::erase_if

These new additions in C++20 bring some serious perks:

  1. Readability: Your code becomes a breeze to read because these functions spell out your intent—removing elements—right in their names.
  2. Simplicity: One function call does the trick, no more convoluted loops or DIY removal code.
  3. Safety: Standard library functions are your trusty sidekicks, reducing the risk of bugs and odd edge cases in your element removal logic.
  4. Performance: These functions are turbocharged for efficiency, so your code stays zippy even when you’re juggling large containers.

In Conclusion

Say goodbye to the headaches of element removal and embrace the simplicity of std::erase and std::erase_if. They make your code cleaner, more readable, and safer. Whether you’re cleaning up by value or on your custom criteria, C++20 has your back. So go ahead, give these new features a whirl in your C++ projects, and let your code shine. Happy coding! 🚀👨‍💻

Introspect mapbox::value

When you’re working with container types that can hold arrays, objects or values, it might be very beneficial if you could look inside to discover its structure and the value it holds. Using the API might be cumbersome, but luckily we can use the toJson() method to dump its content to the console, like so:

value.toJson()

mapbox::value is a type from the Mapbox GL Native library that can hold a variety of different data types (e.g. integers, strings, arrays, etc.). To introspect a mapbox::value object, you can use the following methods:

  1. type() method: This method returns an enumeration value indicating the type of data stored in the mapbox::value object. For example, if the mapbox::value object holds an integer, the type() method will return mapbox::value_type::number_integer.
  2. get_value_type() method: This method returns a string representation of the type stored in the mapbox::value object. For example, if the mapbox::value object holds a string, the get_value_type() method will return “string”.
  3. get<T>() method: This method allows you to access the underlying value stored in the mapbox::value object. You need to specify the data type T that you expect to retrieve. If the type stored in the mapbox::value object is different from T, a mapbox::util::bad_cast exception will be thrown.
  4. is<T>() method: This method allows you to check if the mapbox::value object holds a value of type T. It returns true if the underlying value is of type T, and false otherwise.

You can use these methods to introspect a mapbox::value object and determine its type and underlying value. Once you have determined the type and value of the mapbox::value object, you can use the appropriate methods to access and manipulate the value as needed.

Let’s dive a bit deeper into how you can leverage these methods.

Using type() to Determine Data Type

Consider a scenario where you have a mapbox::value object, but you’re not sure what type of data it holds. The type() method comes to the rescue. Here’s how you can use it:

mapbox::value myValue = …; // Your mapbox::value object
switch (myValue.type()) {
    case mapbox::value_type::number_integer:
        // Handle integer data
        break;
    case mapbox::value_type::string:
        // Handle string data
        break;
    case mapbox::value_type::array:
        // Handle array data
        break;
    // Add more cases for other data types as needed
}
By examining the result of type(), you can take appropriate actions based on the actual data type.

Getting the String Representation with get_value_type()

Sometimes, you might not need the specific enumeration value returned by type(). Instead, you might prefer a more human-readable representation of the data type. This is where get_value_type() shines:

mapbox::value myValue = …; // Your mapbox::value object

std::string valueType = myValue.get_value_type();

// Now, valueType contains a string representation of the data type.

This string can be helpful for logging, reporting, or simply for making your code more understandable.

Accessing the Underlying Value with get<T>()

To access the actual value contained within a mapbox::value object, you can use the get<T>() method. Specify the data type T that corresponds to the expected data type. If the mapbox::value object doesn’t hold a value of that type, an exception will be thrown. Here’s an example:

mapbox::value myValue = ...;  // Your mapbox::value object

try {
    int intValue = myValue.get<int>();  // Attempt to get an integer value
    // Handle intValue
} catch (const mapbox::util::bad_cast&) {
    // Handle the case where myValue doesn't contain an integer
}

This approach ensures type safety and helps prevent runtime errors caused by incompatible data types.

Checking the Type with is<T>()

Before attempting to access the value with get<T>(), you might want to check if the mapbox::value object actually holds a value of a specific type. This can be done using the is<T>() method:

mapbox::value myValue = ...;  // Your mapbox::value object

if (myValue.is<int>()) {
    // myValue contains an integer
    int intValue = myValue.get<int>();
} else {
    // Handle the case where myValue is not an integer
}

This approach allows you to safely access the value only if it matches the expected type.

Introspecting a mapbox::value object doesn’t have to be a daunting task. By using the type(), get_value_type(), get<T>(), and is<T>() methods, you can confidently explore the contents of these versatile objects. Whether you’re parsing JSON data, working with Mapbox GL Native, or dealing with any other scenario involving mapbox::value, these introspection techniques will be your reliable companions in understanding and handling your data. Happy coding!

The mysterious –> operator in C++

The C++ –> is used for … well. I came across this post on Stackoverflow where someone asks what the –> operator in C++ is for, with the following code snippet:

I asked ChatGPT what the –> operator is, and it correctly stated that it “appears to use a non-standard and unconventional usage of the --> operator, which is not a standard operator in C++.” – which is quite good considering the hallucination it often shows. Furthermore, it says:

In C++, the --> operator doesn’t have any predefined meaning or behavior. Instead, it appears that the code you’ve shown is trying to use the -- (decrement) operator followed by the > (greater than) operator. However, this is not valid C++ syntax.

This is pretty much in line with the answer of the post on Stack Overflow.

Just for the fun, I asked ChatGPT how an implementation would look like if it was a valid operator, and this is what it came up with:

Now I asked it if it could imagine what the –> operator could be used for. Here is the answer:

Let’s imagine a use case for the --> operator in a hypothetical scenario:

Suppose you are working on a complex numerical simulation or mathematical modeling library in C++. In such a library, you might frequently work with mathematical expressions and matrices. You could use the --> operator as a custom operator for matrix operations, specifically for updating matrix elements in a concise and intuitive way.

It also mentions I should keep in mind that this is entirely speculative, as the --> operator doesn’t exist in the C++ language, and inventing custom operators should be done judiciously and with care for code readability and maintainability.

Then it produced some code:

  • The --> operator is overloaded for the Matrix class to update individual elements of the matrix.
  • The operator takes a pair of indices (row and column) and returns a reference to the corresponding matrix element.
  • It performs bounds checking to ensure that the indices are within the matrix dimensions.

Well, if C++ had a --> operator, we’d probably have debates about whether it should be called the “rocket ship operator” or the “arrow arrow operator.” And we’d have t-shirts with clever slogans like “I put the ‘fun’ in ‘function'” for C++ developers who love their custom operators. But for now, let’s stick with the good ol’ . and -> and leave the hypothetical operators to our wildest coding dreams! 😄

C++ map quick example

Here’s a quick example of using a C++ map:

#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> grades;
    grades["John"] = 85;
    grades["Jane"] = 92;
    grades["Jim"] = 78;

    std::cout << "John's grade: " << grades["John"] << std::endl;
    std::cout << "Jane's grade: " << grades["Jane"] << std::endl;
    std::cout << "Jim's grade: " << grades["Jim"] << std::endl;

    return 0;
}

In this example, we use a std::map to store the grades of three students (John, Jane, and Jim). Each student’s name is used as a key to look up their corresponding grade. The code uses the [] operator to insert new grades into the map and to look up existing grades.

When we run this program, it outputs the following:

John’s grade: 85

Jane’s grade: 92

Jim’s grade: 78

This demonstrates how a std::map can be used to store key-value pairs and look up values based on keys. It’s a powerful and flexible container that can be used in many applications.

NanoHTTPD

NanoHTTPD is a tiny http server which can be used for testing.

It is a lightweight and simple HTTP server library written in C++. It provides a convenient way to serve HTTP content, such as HTML pages, images, and JSON data, directly from your Java applications. NanoHTTPD is easy to use, fast, and suitable for both small and large projects and is a great choice in automated tests.

Benefits of Using NanoHTTPD

  1. Lightweight and Simple: NanoHTTPD is a compact library, making it easy to integrate into your projects and keep your application size small. The library has a simple and intuitive API, making it easy to understand and get started with.
  2. Flexible: NanoHTTPD is highly flexible and customizable, allowing you to create custom responses and handling of requests to fit your specific needs. You can serve content in any format, such as HTML, images, and JSON, and you can handle requests for specific routes, perform authentication, and implement custom error handling.
  3. Fast: NanoHTTPD uses non-blocking I/O and is optimized for high performance, making it suitable for high-traffic applications. The library is capable of handling many concurrent connections, ensuring fast and responsive serving of content.
  4. Cross-platform: NanoHTTPD is written in Java and runs on any platform that supports Java, making it a cross-platform solution.

Getting Started with NanoHTTPD in Typescript

To start using NanoHTTPD, you need to include the library in your project. You can either download the library and include it in your project manually or use a build tool such as Maven or Gradle to manage your dependencies.

Once you have included the library, you can create a new NanoHTTPD server by extending the NanoHTTPD class and implementing the serve method. In the serve method, you can define the behavior of your server, such as handling requests and returning responses.

Here’s an example of a simple NanoHTTPD server that returns a “Hello, World!” message, in Typescript:

import fi.iki.elonen.NanoHTTPD;

public class HelloWorldServer extends NanoHTTPD {
    public HelloWorldServer() {
        super(8080);
    }
    
    @Override
    public Response serve(IHTTPSession session) {
        return newFixedLengthResponse("Hello, World!");
    }
    
    public static void main(String[] args) {
        new HelloWorldServer().start();
    }
}

In this example, the server listens on port 8080 and returns a “Hello, World!” message for every request. You can start the server by calling the start method, and it will listen for incoming requests until it is stopped.

Customizing Responses

NanoHTTPD provides several methods for returning custom responses, including returning HTML pages, images, and JSON data. You can use the newFixedLengthResponse method to return a custom response, and you can specify the response body, headers, and status code.

NanoHTTPD in C++

Here’s an example of a NanoHTTPD server that returns an HTML page, this time in C++:

#include <iostream>
#include "NanoHTTPD.h"

class HtmlServer : public NanoHTTPD {
 public:
  HtmlServer() : NanoHTTPD(8080) {}

  Response *serve(const Request &request) override {
    std::string html = "<html>"
                       "<body>"
                       "<h1>Hello, World!</h1>"
                       "</body>"
                       "</html>";

    return new Response(Response::OK, "text/html", html);
  }
};

int main(int argc, char **argv) {
  HtmlServer server;
  server.start();

  return 0;
}

This code creates a simple HTTP server that returns an HTML page with a “Hello, World!” heading. The Response constructor is used to return the HTML content, and the response type is set to “text/html”. The status code is set to Response::OK to indicate that the request was successful.

This is just a simple example, but you can extend it to return more complex content and handle different types of requests.

C++ Modules, since C++20

C++ Modules are a way to organize and manage code in large C++ projects.

Imagine you have a big project with many files and libraries, and each file depends on other files and libraries. Currently, in C++, to use a piece of code from another file, you have to include a header file with declarations, which can result in slow build times and difficult-to-manage dependencies.

C++ Modules aim to solve this problem by allowing you to package up all the code from a library into a single “module” file. You can then import this module into your own code, and you’ll have access to all the code in the module without having to include individual header files. This leads to faster build times and easier-to-manage dependencies.

Think of modules as containers for your code that make it easier to reuse and share with others, without having to worry about the details of how the code is organized or which files depend on which other files.

std::expected in C++23

std::expected is a type defined in the C++23 standard library as a way of handling errors in C++. It is used to represent the result of an operation that may either produce a value or an error. It provides a way to handle expected results in a type-safe and exception-free manner.

The std::expected template has two template parameters: the first is the type of the value that the operation may produce, and the second is the type of the error that the operation may return. The std::expected object can be in one of two states: a valid state, in which it holds a value, or an invalid state, in which it holds an error.

You can use the std::expected object just like a regular value, with the advantage that you can also check if the operation was successful or not. You can use the value() member function to access the stored value, or the error() member function to access the stored error. If the std::expected object is in the invalid state and you try to access the value, a compile-time error will occur.

Here is an example of using std::expected:

#include <iostream>
#include <expected>
#include <string>

std::expected<std::string, std::string> get_greeting(bool happy)
{
    if (happy) {
        return std::string("Hello, friend!");
    } else {
        return std::make_unexpected(std::string("Oh no, something went wrong."));
    }
}

int main()
{
    auto greeting = get_greeting(true);
    if (greeting) {
        std::cout << *greeting << std::endl;
    } else {
        std::cout << greeting.error() << std::endl;
    }
    return 0;
}

In this example, the get_greeting function returns a std::expected<std::string, std::string> object. If the happy argument is true, the function returns a string with a friendly greeting. If happy is false, the function returns an error message using std::make_unexpected.

In the main function, the code checks the state of the std::expected object. If the std::expected object is in the valid state, it contains the greeting and the code outputs the greeting to the console. If the std::expected object is in the invalid state, it contains the error message and the code outputs the error message to the console.

This example demonstrates how std::expected provides a way to handle expected results in a type-safe and exception-free manner, allowing you to check for success or failure and respond accordingly.

Why exception free

std::expected is exception-free because it doesn’t use exceptions to signal error conditions. Instead, it uses a return value to indicate success or failure, which can be checked using the valid() member function or by casting the std::expected object to a bool.

The advantage of using std::expected over exceptions is that it provides a clear and predictable way to handle error conditions. With exceptions, it can be difficult to know exactly where an exception will be thrown, making it harder to write robust and maintainable code. With std::expected, you can see from the function signature what type of error the function might return, and you can handle the error directly in the code that calls the function. This makes it easier to reason about the behavior of your code and to avoid unintended side effects.

In addition, using std::expected can also be more efficient than using exceptions because it avoids the overhead of constructing and unwinding the stack for each exception. This can make your code faster and more scalable, especially in resource-constrained environments where performance is critical.

This is an update to an earlier article where I explained std::expected before it was introduced to the C++23 standard library.

How to inspect your C++ code after preprocessor

In C++, the preprocessor is a tool that performs a series of transformations on the source code before it is compiled. It performs operations such as macro expansion, inclusion of header files, and conditional compilation.

One reason why it can be useful to see what the preprocessor produces in C++ is to understand how the code is transformed before it is compiled. The preprocessor can expand macros, substitute values, and perform other transformations that can significantly change the code structure. By examining the preprocessed output, developers can see how their code is transformed and check whether it is behaving as expected.

Additionally, examining the preprocessor output can help to diagnose errors and bugs in the code. By looking at the expanded code, developers can identify issues such as incorrect macro expansion, missing header files, or other problems that may arise during compilation.

Another reason why it can be useful to see the preprocessor output is to optimize the code. By examining the preprocessed code, developers can identify redundant operations, unnecessary inclusions of header files, and other areas where the code can be streamlined for better performance.

Overall, examining the preprocessor output in C++ can be a useful tool for understanding how the code is transformed before it is compiled, diagnosing errors and bugs, and optimizing the code for better performance.

How?

So, we understand that sometimes it can be very useful to see what the preprocessor actually produces before handling over the file to the compiler. You can inspect details and track down some type of problems. There are a few ways to do this:

gcc -E my_class.cpp -o my_class.ii

or

cpp my_class.cpp >> my_class.ii

Or if you work with qmake, you can use:

QMAKE_CXXFLAGS += -save-temps

In which case you will also get these *.ii files for each *.cpp file in your build folder. When we look inside such a file we see a lot more stuff than we wrote. For example line markers around the include statements:

# 1 "/usr/local/include/something.h" 1 3 4

The 3 means the import comes from a system header, 4 means the import should be wrapped in a ‘extern “C”‘ block.

This and what the other numbers mean is explained here: https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html

Happy Debugging!

Qt application on Windows not starting

When you click on an applications exe file and nothing happens, you might wonder what it does (if anything) and find a way to debug what is happening. By default, the binary does not output any log to the console. But there is a way to do that.

You can rebuild your Qt app using the console qmake flag in order to get some useful debugging output on the console.

CONFIG += console

either in your QtCreator Build Settings or as a command line argument to qmake. Then run the app exe from a Windows terminal such as PowerShell and you will see the same output you would see in QtCreator, including your qDebug outputs. You can also click on it in the explorer and it opens a standard terminal showing the console output.

This can be very useful, e.g. when debugging a sandbox created with windeployqt.