siware.dev

Useful C++ Code Snippets

Some useful C++ code snippets that I find useful from time to time.

Simple Profiling

If you want to get statistical confidence, just use google benchmark https://github.com/google/benchmark. Otherwise, simple profiling can be done with chrono:

#include <chrono>
...
	auto start = std::chrono::high_resolution_clock::now();
    ...
	auto end = std::chrono::high_resolution_clock::now();
	auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

	std::cout << "Duration: " << duration.count() << "ms\n";

Transaction Pattern

Sometimes it’s useful to have transactional code block where we can undo/commit a block of operations. We can use C++ RAII to do this:

class Transaction
{
    bool committed = false;
    // state
public:
    Transaction(/*some state*/) { ... }
    ~Transaction() { if (!committed) { /*undo operation*/ } }
    void Commit() noexcept { committed = true; }
}

Example usage is parsing where we want to parse a sequence-of-token or not at all

void ParseSequence()
{
    Transaction transaction(tokenizer);

    if (!tokenizer.Next(TokenType::Comma))
        return; // automatically revert any changes

    if (!tokenizer.Next(TokenType::StringLiteral))
        return // automatically revert any changes

    transaction.Commit(); // all operations succeeded
}

Get or Create std::map, std::unordered_map

std::unordered_map<Key, Value> map;
auto [iter, newEntry] = map.emplace(key, Value{});
if (newEntry)
    iter->second = Value();

Loop over map

std::unordered_map<Key, Value> map;
for (const auto& [key, value] : map)
{
    ...
}

String Format

template < typename... Args >
inline std::string StringFormat(const char *format, Args... args)
{
    size_t size = std::snprintf(nullptr, 0, format, args...) + 1; // Extra space for '\0'

    auto buf = std::make_unique< char[] >(size);
    std::snprintf(buf.get(), size, format, args...);

    return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
}

Printf tricks

Print the first n characters:

const char* pStr = "C Tips and Tricks.";
printf( "%.*s\n", 5, pStr);  // This will print "C Tips"

Print n spaces:

printf("%*s", 5, ""); // This will print "     "

Unicode printf-style format specifiers

Complete story: https://devblogs.microsoft.com/oldnewthing/20190830-00/?p=102823

// Stick to %hs and %ls for compatibility between Windows and C
const char* narrowStr = "hello narrow";
const wchar_t* widestr = L"hello wide";
printf("%hs", narrowStr);
printf("%ls", wideStr);

Using <charconv>

C++17 has <charconv> that is useful to convert text to/from number.

#include <charconv>
const char* text = "123";
int value;
if (std::from_chars(text, text + std::strlen(text), value).ec == std::errc{})
{
    // succeed
}

Class member size and offset

struct MyStruct
{
    int field0;
    char field1;
};
sizeof( MyStruct::field0 )
offsetof( MyStruct, field0 )

Transferring ownership

std::unique_ptr<T> ptr;
...
using Storage = typename std::aligned_storage<sizeof(NonConstT), alignof(NonConstT)>::type;
std::unique_ptr<Storage> stPtr = std::make_unique<Storage>();

// Transfer ownership to correct unique_ptr type
ptr.reset( reinterpret_cast<T *>( stPtr.release() ) );