Skip to main content

Get the Reddit app

Scan this QR code to download the app now
Or check it out in the app stores
r/cpp icon
r/cpp icon

r/cpp

members
online

C++ Jobs - Q3 2024
MOD

Rules For Individuals

  • Don't create top-level comments - those are for employers.

  • Feel free to reply to top-level comments with on-topic questions.

  • I will create top-level comments for meta discussion and individuals looking for work.

Rules For Employers

  • If you're hiring directly, you're fine, skip this bullet point. If you're a third-party recruiter, see the extra rules below.

  • Multiple top-level comments per employer are now permitted.

    • It's still fine to consolidate multiple job openings into a single comment, or mention them in replies to your own top-level comment.

  • Don't use URL shorteners.

    • reddiquette forbids them because they're opaque to the spam filter.

  • Use the following template.

    • Use **two stars** to bold text. Use empty lines to separate sections.

  • Proofread your comment after posting it, and edit any formatting mistakes.

Template

**Company:** [Company name; also, use the "formatting help" to make it a link to your company's website, or a specific careers page if you have one.]

**Type:** [Full time, part time, internship, contract, etc.]

**Compensation:** [This section is optional, and you can omit it without explaining why. However, including it will help your job posting stand out as there is extreme demand from candidates looking for this info. If you choose to provide this section, it must contain (a range of) actual numbers - don't waste anyone's time by saying "Compensation: Competitive."]

**Location:** [Where's your office - or if you're hiring at multiple offices, list them. If your workplace language isn't English, please specify it. It's suggested, but not required, to include the country/region; "Redmond, WA, USA" is clearer for international candidates.]

**Remote:** [Do you offer the option of working remotely? If so, do you require employees to live in certain areas or time zones?]

**Visa Sponsorship:** [Does your company sponsor visas?]

**Description:** [What does your company do, and what are you hiring C++ devs for? How much experience are you looking for, and what seniority levels are you hiring for? The more details you provide, the better.]

**Technologies:** [Required: what version of the C++ Standard do you mainly use? Optional: do you use Linux/Mac/Windows, are there languages you use in addition to C++, are there technologies like OpenGL or libraries like Boost that you need/want/like experience with, etc.]

**Contact:** [How do you want to be contacted? Email, reddit PM, telepathy, gravitational waves?]

Extra Rules For Third-Party Recruiters

Send modmail to request pre-approval on a case-by-case basis. We'll want to hear what info you can provide (in this case you can withhold client company names, and compensation info is still recommended but optional). We hope that you can connect candidates with jobs that would otherwise be unavailable, and we expect you to treat candidates well.

Previous Post


C++ Show and Tell - July 2024


[C++20] mp2.0 - Back to the Future Meta-Programming! (ranges, reflection / msvc, gcc, clang) [C++20] mp2.0 - Back to the Future Meta-Programming! (ranges, reflection / msvc, gcc, clang)

Meta-Programming is one of the C++ super-powers

Traditional meta-programming model in C++ is very powerful but not the easiest to understand. Mainly because it has different syntax than 'normal' C++ with a lot of angle brackets, it's functional, immutable, etc.

There are some great template meta-programming libraries available such as boost.mp11 - https://www.boost.org/doc/libs/1_85_0/libs/mp11/doc/html/mp11.html which make template meta-programming much easier, but the question still remains - can we make meta-programming simpler/closer to 'normal' C++? And if so, what are the trade-offs? All in all, wouldn't be great to be able to write the same code for run-time and compile-time and/or debug compile-time code at run-time?

Reflection for C++ - https://wg21.link/P2996 - introduced a new meta-programming model which is value/consteval based and can greatly improve the experience. Together with reflection is a very powerful combination but it also has its own set of trade-offs such as slower compilation-times and some syntax/API quirks but nothing major. It's likely to be part of C++26 but is there anything we can do in the meantime to improve meta-programming experience?

That's where mp - https://github.com/boost-ext/mp comes in handy - C++20 (msvc, gcc, clang) meta-programming library which supports meta-programming model similar to P2996 with a bit faster compilation times and very simplistic API. Most importantly, though, mp makes meta-programming as close to the 'normal' C++ as possible. In the mp world there is no difference between run-time and compile-time, the whole standard library can be leveraged including ranges. It also has reflection integration using C++20 - https://github.com/boost-ext/reflect. Of course it has its own set of trade-offs but, IMHO, it has a lot of potential and it's super fan!

  • Note: Most of the mp API can work with C++17.

Example (API)

// mp::meta
static_assert(mp::meta<int> == mp::meta<int>);
static_assert(mp::meta<int> != mp::meta<void>);
static_assert(typeid(mp::meta<int>) == typeid(mp::meta<void>));

// mp::type_of
constexpr mp::info meta = mp::meta<int>;
mp::type_of<meta> i{}; // same as int i{};
mp::type_of<mp::meta<bool>> b = true; // same as bool b = true;

// mp::apply
template<class...> struct type_list{ };
static_assert(std::is_same_v<type_list<int, int>, mp::apply_t<type_list, mp::array{meta, meta}>>);

// mp::invoke
static_assert(not mp::invoke<std::is_const>(meta));
static_assert(std::is_same_v<const int, mp::type_of<mp::invoke<std::add_const>(meta)>>);

// hello world
template<size_t N, class... Ts>
using at_c = mp::type_of<std::array{mp::meta<Ts>...}[N]>;

static_assert(std::is_same_v<int, at_c<0, int, bool, float>>);
static_assert(std::is_same_v<bool, at_c<1, int, bool, float>>);
static_assert(std::is_same_v<float, at_c<2, int, bool, float>>);

// ranges
template<class... Ts>
constexpr mp::vector ranges =
    std::array{mp::meta<Ts>...}
  | std::views::drop(1)
  | std::views::reverse
  | std::views::filter([](auto m) { return mp::invoke<std::is_integral>(m); })
  | std::views::transform([](auto m) { return mp::invoke<std::add_const>(m); })
  | std::views::take(2)
  ;

static_assert(std::is_same_v<
  std::variant<const int, const short>, 
  mp::apply_t<std::variant, ranges<double, void, const short, int>>
>);

// reflection (requires https://github.com/boost-ext/reflect)
struct foo {
  int a;
  bool b;
  float c;
};

foo f{.a = 42, .b = true, .c = 3.2f};

constexpr mp::vector v = reflexpr(f)
  | std::views::filter([&](auto meta) { return member_name(meta, f) != "b"; })
  ;

static_assert(std::tuple{42, 3.2f} == unreflexpr<std::tuple, v>(f));

Full example - standalone - https://godbolt.org/z/Mjcxedzzj

Full example - reflection - https://godbolt.org/z/ds3KMGhqP

Library - https://github.com/boost-ext/mp

Supported compilers - https://godbolt.org/z/qarWdbK79

Compilation times benchmark - https://boost-ext.github.io/mp

P2996 (C++26*) mp (C++20)
^T meta<T>
typename [: T :] type_of<T>
template for (https://wg21.link/p1306) for_each
substitute apply
value_of<R>(reflect_invoke(^fn, {substitute(^meta, {reflect_value(m)})})) invoke(fn, m)

Updates - https://x.com/krisjusiak/status/1812744501636505616



New C++ Conference Videos Released This Month - July 2024 (Updated To Include Videos Released 07/08/2024 - 07/14/2024) New C++ Conference Videos Released This Month - July 2024 (Updated To Include Videos Released 07/08/2024 - 07/14/2024)

This month the following C++ videos have been published to YouTube. A new post will be made each week as more videos are released

ACCU Conference

07/08/2024 - 07/14/2024

07/01/2024 - 07/07/2024

C++Now

07/08/2024 - 07/14/2024

C++Online

07/08/2024 - 07/14/2024

07/01/2024 - 07/07/2024

Audio Developer Conference

07/08/2024 - 07/14/2024

07/01/2024 - 07/07/2024



Creating a Test Report document using Cpp Creating a Test Report document using Cpp

Hi everyone. I am relatively new at cpp, but I have a mini project I would like to complete if possible. I am a test lab intern at Dana inc. and was wondering if it is possible to automate the engineers test reports. My engineer mentor mentioned that it would be nice if this could be done. Currently, they use microsoft word and have a template already, but they would like an executable file where it prompts the user to input certain responses. After they submit all the responses, the program will generate the fully formatted report.

Any guidance on this would be appreciated! Thank you


C++20 modules with Clang-CL: which way forward? C++20 modules with Clang-CL: which way forward?

This has been bothering me for a long time, and given the stalemates I've seen everywhere, I'd like to ask what the stakeholders in the community think. This is a surprisingly simple issue but affects a lot of people.

Preamble

Clang-CL is a compiler driver for Clang/LLVM that supports MSVC's cl.exe command-line options, on top of supporting Clang's own options.

It is not a different compiler to Clang; in fact, the clang-cl.exe and clang.exe binaries in the official LLVM releases are bit-identical with equal checksums. Only the file name is different. On Linux, you could rename /usr/bin/clang to /usr/bin/clang-cl (which incidentally might already be present, depending on the distro and package) and try to run clang-cl main.cpp, and suddenly you have a compiler that will automatically look for (and probably fail to find) the Windows SDK and the MSVC C/C++ headers and libraries, and will target x86_64-pc-windows-msvc (i.e. the MSVC C++ ABI) without explicitly having to specify anything.

This behaviour may also be controlled in the command-line with --driver-mode. You can send normal Clang into Clang-CL mode with --driver-mode=cl. Similarly, you can force Clang to compile a file with a .c extension as C++ with --driver-mode=g++ (and vice-versa, with gcc).

The problem

clang has supported C++ modules in some form since Clang 15-16, which got a lot more stable in Clang 17, and I daresay is fully usable with Clang 18 (with some minor niggles). Given the above preamble, you'd expect Clang-CL to operate exactly the same way, which is not the case. The Hello World example for C++20 modules with Clang turns into the following with Clang-CL:

clang-cl.exe /std:c++20 .\Hello.cppm /clang:--precompile /Fo.\Hello.pcm
clang-cl.exe /std:c++20 use.cpp /clang:-fmodule-file=Hello=Hello.pcm .\Hello.pcm /Fo.\Hello.out

.\Hello.out
Hello World!

Okay, we need /clang:; big deal. This is alright when working off the command-line or in Makefiles (where the command-line invocation is manually specified anyway), but somehow the modern build systems—CMake and MSBuild; not entirely sure about Meson, Build2, and XMake—have collectively decided that 'Clang-CL does not support C++20 modules'.

I have opened/found the following threads/comments about the issue (the first is a year old, I can't believe it):

From what I see, discussion has stalled. There are a few options:

  • Expect and allow Clang-CL to accept Clang's -fmodule-* and --precompile as first-class citizens, i.e. without /clang:.

    • This is straightforward—a handful of one-liners which I have just submitted.

    • This means accepting that Clang-CL's module handling is different to CL's, and accounting for this in all build systems.

  • Require Clang-CL (and therefore, Clang) to support MSVC's /ifc* arguments, and therefore, imply that Clang emits MSVC-compatible IFCs.

    • This requires some serious mangling that will probably involve all three of the driver, front-end, and back-end.

    • However this is what many build system authors and users expect: for Clang-CL to behave exactly like CL.

Personally, I feel there is existing precedent for Clang-CL's behaviour to diverge from CL's, which honestly should be expected: they're different compilers, after all. For instance, link-time/whole-program/inter-procedural optimisation is handled in Clang-CL using -flto=thin. It doesn't even have MSVC's /GL and /LTCG. The interim object binaries emitted are incompatible, too.

I'm inclined to believe C++ modules are a very similar situation, especially given all implementations rely deeply on compiler internals. In fact one can't even mix .pcm files compiled by Clangs with different Git commit hashes.

I'd love to spur some discussion about this, which I daresay is one of the last few BIG issues with C++20 modules. Clang and MSVC devs, build system authors, and users, do say what you think.


† Fun fact, this setup completely obviates and is probably superior to MinGW as a Windows cross-compiler for Linux, especially if you go the full bore and mount the real MSVC headers, libraries, and Windows SDK in a case-insensitive filesystem like the Firefox guys have done.


Difference between initializer lists? Difference between initializer lists?

I'm reading Jason Turner's Best Practices (https://leanpub.com/cppbestpractices) (no affiliation, just enjoy his content).

Anyways, from one of the chapters, he asks the reader to explain the difference between the following as an exercise:

std::array<std::shared_ptr<char>, 2> data {
    std::make_shared<char>(40), std::make_shared<char>(2)
};

std::vector<std::shared_ptr<char>> vec {
    std::make_shared<char>(40), std::make_shared<char>(2)
};

(Specifically, I believe he means the difference with respect to how the initializer list works // allocations).

I ran these examples on compiler explorer while overloading the `new` operator, and the results are interesting (see link below) - `vec` has an extra 32 byte allocation. Anyone understand where that comes from...?

https://godbolt.org/z/e6GYcafh9


Dual Build Mode: Header Includes or Module Imports Dual Build Mode: Header Includes or Module Imports

I am working on making a large legacy codebase "module ready". My plan is to use a CMake option (e.g., -D USE_MODULES=ON) to switch from header includes to module imports. This should require minimal changes to the current .hpp/.cpp files, and I intend to create a thin wrapper module.

I found this reddit post by u/Daniela-E where she explains how she transformed the header-only fmt library to support such a dual build mode. However, I've encountered challenges applying this approach to libraries with source files (i.e., not header-only).

I've created a working solution in this repository (particularly note the 06/ folder) and wrote a related blog post discussing the implementation.

Has anyone else attempted something similar or found a better solution? Links to dedicated blog posts, repositories, or YouTube talks would be much appreciated.

Additionally, I would welcome any general feedback. Are there any potential pitfalls I haven't addressed yet?

EDIT: The following improvement ideas have been mentioned

  • Allow imports of the same library in the primary module interface and at the same time in the implementation unit. This will lead to less boilerplate (no more additional scanning needed).

  • Convert each cpp file into their own module implementation unit instead of a separate unity build type module implementation unit (possibly faster incremental build times).

  • Make use of import std; if available.


Photoshop API - Read and Write PSD files with Python and C++ Photoshop API - Read and Write PSD files with Python and C++

Hey,

Emil Dohne is creating a modern and performant C++20 read/write parser of Photoshop Files (*.psd and *.psb) with fully fledged Python bindings hosted on PyPi, completely on its own.

I just wanted to help him out trying to make his work known, so that more people can utilize this incredibily useful repo and in order to find someone incredibly talented and kind people that wanted to help him out collaborating in the development! At the moment Emil is occupied by another project that he will end by the end of July and he will then be back 100% on this project.

I reckon that the hierarchy of new features needed/really wanted are the following:

  1. Support for Smart Object Layers - replacing images inside of the smart object

  2. Support for Adjustment Layers

  3. Support for Vector Masks

  4. Support for Text Layers

  5. CMYK, Indexed, Duotone and Greyscale Color Modes

Thank you to whoever even takes the time to read this, let alone whoever shares this project and even more to incredibly smart people that will help Emil out.

Here's some more info about this project: https://github.com/EmilDohne/PhotoshopAPI

About

PhotoshopAPI is a C++20 Library with Python bindings for reading and writing of Photoshop Files (*.psd and *.psb) based on previous works from psd_sdkpytoshop and psd-tools. As well as the official Photoshop File Format Specification, where applicable. The library is continuously tested for correctness in its core functionality. If you do find a bug please submit an issue to the github page.

The motivation to create another library despite all the other works present is that there isn't a library which has layer editing as a first class citizen while also supporting all bit-depths known to Photoshop (8-bits16-bits32-bits). This Library aims to create an abstraction between the raw binary file format and the structure that the user interfaces against to provide a more intuitive approach to the editing of Photoshop Files.

Why should you care?

Photoshop itself is unfortunately often slow to read/write files and the built-in tools for automatically/programmatically modifying files suffer this same issue. On top of this, due to the extensive history of the Photoshop File Format, Photoshop files written out by Photoshop itself are often unnecessarily bloated to add backwards compatibility or cross-software compatibility.

The PhotoshopAPI tries to address these issue by allowing the user to read/write/modify Photoshop Files without ever having to enter Photoshop itself which additionally means, no license is required. It is roughly 5-10x faster in reads and 20x faster in writes than photoshop while producing files that are consistently 20-50% lower in size (see the benchmarks section on readthedocs for details). The cost of parsing is paid up front either on read or on write so modifying the layer structure itself is almost instantaneous (except for adding new layers).

Features

Supported:

  • Read and write of *.psd and *.psb files

  • Creating and modifying simple and complex nested layer structures

  • Pixel Masks

  • Modifying layer attributes (name, blend mode etc.)

  • Setting the Display ICC Profile

  • Setting the DPI of the document

  • 8-, 16- and 32-bit files

  • RGB Color Mode

  • All compression modes known to Photoshop

Planned:

  • Support for Smart Object Layers

  • Support for Adjustment Layers

  • Support for Vector Masks

  • Support for Text Layers

  • CMYK, Indexed, Duotone and Greyscale Color Modes

Not Supported:

  • Files written by the PhotoshopAPI do not contain a valid merged image in order to save size meaning they will not behave properly when opened in third party apps requiring these (such as Lightroom)

  • Lab and Multichannel Color Modes

Python

The PhotoshopAPI comes with fully fledged Python bindings which can be simply installed using

$ py -m pip install PhotoshopAPI

alternatively the wheels can be downloaded from the Releases page. For examples on how to use the python bindings please refer to the Python Bindings section on Readthedocs or check out the PhotoshopExamples/ directory on the github page which includes examples for Python as well as C++.

For an even quicker way of getting started check out the Quickstart section!

Documentation

The full documentation with benchmarks, build instructions and code reference is hosted on the PhotoshopAPI readthedocs page.

Requirements

This goes over requirements for usage, for development requirements please visit the docs.

  • A CPU with AVX2 support (this is most CPUs after 2014) will greatly increase performance, if we detect this to not be there we disable this optimization

  • A 64-bit system

  • C++ Library: LinuxWindows or MacOS

  • Python Library1LinuxWindowsMacOS

The python bindings support python >=3.7 (except for ARM-based MacOS machines which raise this to >=3.10)

Performance

The PhotoshopAPI is built with performance as one of its foremost concerns. Using it should enable you to optimize your pipeline rather than slow it down. It runs fully multithreaded with SIMD instructions to leverage all the computing power your computer can afford.

As the feature set increases this will keep being one of the key requirements. For detailed benchmarks running on a variety of different configurations please visit the docs

Below you can find some of the benchmarks comparing the PhotoshopAPI ('PSAPI') against Photoshop in read/write performance




Speaking of intuitive and hard-to-misuse APIs... Speaking of intuitive and hard-to-misuse APIs...

Is it just me or is this extremely counter-intuitive? (taken from here)

// std::greater<int> makes the max priority queue act as a min priority queue.

It's been years and I still haven't found an easy way to memorise which comparator turns a sort into an ascending and which turns it into a descending order, and this isn't making it any easier. Does anyone have a trick that makes it easier for you?





Seeking Advice on Implementing Modern Logging in C++20 (for a Game Engine) Seeking Advice on Implementing Modern Logging in C++20 (for a Game Engine)

I'm working on a project for learning purposes, specifically a game engine. As part of this, I've been developing a logging component. After researching existing logging implementations (spdlog, Unreal Engine, O3DE, Abseil, gRPC, etc.), I noticed that many are outdated, apart from spdlog. Logging is typically one of the initial components implemented and often lacks newer features.

I'm currently using C++20 and want to understand how modern logging should be implemented. I've created two basic implementations for logging formatted output to the console:

Implementation 1: FormatLogger

    #pragma once

    #include <format>
    #include <string_view>

    class FormatLogger {
    public:
        template<typename... Args>
        void log(std::string_view format, Args &&...args) {
            auto formatted = std::vformat(format, std::make_format_args(args...));
            output(formatted);
        }

    private:
        void output(const std::string &message);
    };

    void FormatLogger::output(const std::string &message) {
        std::cout << message << '\n';
    }

Implementation 2: VAListLogger

    #pragma once

    class VAListLogger {
    public:
        void log(const char* format, ...);

    private:
        static constexpr size_t BUFFER_SIZE = 1024;
        void output(const char* message);
    };

    #include <cstdarg>
    #include <cstdio>

    void VAListLogger::log(const char *format, ...) {
        va_list args;
        va_start(args, format);
        char buffer[1024]; // Adjust size as needed
        vsnprintf(buffer, sizeof(buffer), format, args);
        va_end(args);
        output(buffer);
    }

    void VAListLogger::output(const char *message) {
        printf("%s\n", message);
    }

Performance Comparison

I conducted a simple benchmark by calling each logger 1,000,000 times, printing a formatted string with 200 characters and the value of pi. The results were as follows:

VAListLogger: 81,628 ms
FormatLogger: 53,378 ms

I also built both implementations as static libraries in debug mode:

VAListLogger: 381 KB
FormatLogger: 2.33 MB

The results show that while VAListLogger is smaller in binary size, it is slower. FormatLogger is faster but significantly larger.

I also read Jeremy Ong's blog post which suggests that std::format might not be suitable for game engines due to its impact on binary size and compile times in large codebases.

What else should i consider and what is recommended? (probably nothing of my attempts?)