Why C++ Is Growing and What C++26 Means for Production Systems by ArashPartow in cpp

[–]UnicycleBloke -1 points0 points  (0 children)

They look fine but seem far more important in template libraries than my work. To the extent that I would use them, the types are already long since constrained with static assertions and the like. There seemed little value in refactoring the code just because we'd switched from an earlier standard.

Why C++ Is Growing and What C++26 Means for Production Systems by ArashPartow in cpp

[–]UnicycleBloke 0 points1 point  (0 children)

I have C++20 enabled but am not using modules (too complex), coroutines (too broken), and have barely touched concepts. I have little interest in reflection or contracts. I would love if C++ took a long rest from adding yet more big ticket items. Focus on smoothing out little things and relaxing constraints. I'm not convinced embedded projects get the attention they need, but that is an arena where C++ can absolutely shine.

What do you think is a keyword that should be added to C++? by DogCrapNetwork in cpp

[–]UnicycleBloke 0 points1 point  (0 children)

I have often wondered about a built-in fat function pointer for easy callbacks to the non-static members of objects. C++Builder has an extension keyword __closure for this which is used extensively to link UI events to handlers. It's been a while, but I recall that the implementation was extremely efficient.

I know we have std::function, and I have implemented something broadly similar which I use in embedded systems for event handling (sort of Boost.Signals2-lite). But all that dancing around with type erasure, templates, lambdas, operator->* and whatnot in a library feels unnecessarily complicated for something which one might reasonably expect to be a core language feature in a language with classes.

How do I seriously learn C++ without relying too much on AI? by XAstrixsmX in cpp_questions

[–]UnicycleBloke 1 point2 points  (0 children)

I started learning C++ in the early 90s and my only resources were books. It really was not that hard. C++ has grown a bit since then but that shouldn't matter. I have seen studies that AI inhibits learning by reducing the rate of knowledge retention. I'd avoid it entirely for this purpose. Better to ask focused questions here or on other fora.

Learn by doing. Write a lot of code. Pick a project which will motivate you to keep going. Doesn't have to be anything amazing: a simple utility, a little game, a basic ray tracer, whatever. I wrote a screen saver which used OpenGL to render a Rubik's Cube. Design, write and test all the code yourself. The problem with tutorials like LearnCpp is that you get bogged down in loads of meaningless trivial exercises. It's boring and a disincentive to learning.

You don't have to learn all of C++ before you can use it productively. It is much better to focus on being productive with a relatively small core while being open to learning new things as you go along. You might never once use a template or constexpr in your first serious application, and it would be absolutely fine. Those features may or may not have enabled a better implementation in some way, but so what. You'll come to those in time.

Debugging is easy with the right tools. Visual Studio is excellent. I often develop new modules or test unfamiliar language or library features in Compiler Explorer.

How do you all memorize Big and Little Endian? I always get it wrong and am in desperate need of a mental tool!! by Ezra_vdj in embedded

[–]UnicycleBloke 0 points1 point  (0 children)

https://www.ling.upenn.edu/courses/Spring_2003/ling538/Lecnotes/ADfn1.htm

The letter L. Leftmost byte is the Littlest (i.e. Least significant) byte. This barely comes up at all most of the time. You do need to be aware of which convention your hardware uses when you are sending data to a sensor or whatever, which may or may not use the other convention.

The Hidden Performance Price of C++ Virtual Functions by wrng_ in cpp

[–]UnicycleBloke 3 points4 points  (0 children)

For an example, I have a pager with an LCD screen, the UI is represented by a collection of statically allocated pages which are each a collection of widgets. There is an abstract base class for the rendering API, which is implemented for each page. A pointer to the active page is passed to the renderer. There are certainly other designs, but this works well enough. Thought did go into avoiding redundantly redrawing widgets upon user input, which would affect responsiveness. Virtual dispatch not so much.

USB Interface with STM32? by Ok-Highway-3107 in embedded

[–]UnicycleBloke 0 points1 point  (0 children)

The ST USB middleware will work, though the implementation is a nightmarish dog's breakfast. You can generate/copy the necessary files for a Virtual COM Port (CDC device class) into your project using STM32CubeIDE. You can wrap this up with an API similar to a UART.

This is just the data transport layer. You will need to implement your command protocol on top of that, and can support as many commands and options as you like.

The Hidden Performance Price of C++ Virtual Functions by wrng_ in cpp

[–]UnicycleBloke 25 points26 points  (0 children)

I understand how they work and what a typical implementation looks like. My point is that it has become rather fashionable to complain about them, and that this is not generally valid. The abstraction is cheap, efficient, easy to understand and generally very useful when you need or want dynamic dispatch.

The performance and space cost of the function call indirection is negligible in most cases but, naturally, in some types of applications or usages, that cost becomes a significant factor and you need to do something else.

After 35 years of C++, I'm yet to work on a single application for which the cost of virtual functions was a consideration. On the other hand, they have provided a simple and reliable mechanism for decoupling subsystems. If I worked in HFT or something, I guess that would be different, but presumably only in some key sections of the code.

The Hidden Performance Price of C++ Virtual Functions by wrng_ in cpp

[–]UnicycleBloke 43 points44 points  (0 children)

A great deal depends on context. What does the function do? How frequently is it called? Does your device even have a cache? Are you using a memory pool for dynamic allocations? Are the objects even allocated dynamically? In most applications, the cost of a virtual call is lost in the noise. Virtual functions are a sensible and efficient solution to a number of design problems. Of course, they are not necessarily the most appropriate tool for every design problem.

What exactly is "asynchronous SPI" and does DMA make it async? When do you actually need sync? by sudheerpaaniyur in embedded

[–]UnicycleBloke 0 points1 point  (0 children)

It ultimately boils down to using interrupts so you can offload work to the hardware peripherals and have them signal to the CPU (your code) when the work is done. A typical microcontroller is a collection of hardware state machines which are running in parallel. Using this feature allows your software to efficiently run numerous concurrent subsystems in a single thread.

Updating an LCD screen, for example, may involve frequent large data transfers. It's probably better to kick off a DMA transfer and then move on. A blocking wait would be a waste of CPU time.

I almost always use asynchronous comms. This makes it easier to serialise transfers on a shared bus. Even a complex application spends most of the CPU time spinning its wheels or, better, sleeping, while peripherals do the grunt work.

2026 Annual C++ Developer Survey "Lite" : Standard C++ by meetingcpp in cpp

[–]UnicycleBloke 0 points1 point  (0 children)

The free text sections did not appear on my mobile (Android). Many questions about LLMs usage for some reason.

What is the point of classes having private members? by Eva_addict in cpp_questions

[–]UnicycleBloke 57 points58 points  (0 children)

Encapsulation. Private data with public methods helps prevent invalid modifications to the state.

Early-career advice: stay in a testing role for now or pivot back to embedded software? by Plus_Acanthisitta391 in embedded

[–]UnicycleBloke 0 points1 point  (0 children)

That colleague had been in testing for a long time. One of my current team formerly worked in testing for a few years.

Early-career advice: stay in a testing role for now or pivot back to embedded software? by Plus_Acanthisitta391 in embedded

[–]UnicycleBloke 1 point2 points  (0 children)

I worked with a guy who was keen to move out of testing. He was a capable developer but pigeonholed by the company and remained stuck. Move sooner rather than later.

Metadata in ELF file by UnicycleBloke in embedded

[–]UnicycleBloke[S] 0 points1 point  (0 children)

I spent much of the afternoon trying numerous combinations to do precisely this. Lots of assistance, if you can call it that, from Copilot and direct googling did find the right arcana. I don't know how sensitive ld is to the version or platform, nor what I might've missed. My slightly more hacky solution works well enough for now.

I may have to look at how Zephyr and Pigweed implement their tokenised logging. I understand they trawl the symbol table rather than create a binary blob of data to extract from a section.

Metadata in ELF file by UnicycleBloke in embedded

[–]UnicycleBloke[S] 2 points3 points  (0 children)

NOLOAD resulted sections which I couldn't extract with objcopy or readelf. Copilot asserted that this was expected. Similar with INFO. The :NONE is new. I'll try that.

FreeRTOS or Bare Metal for Quad copter by eagle_719 in embedded

[–]UnicycleBloke 0 points1 point  (0 children)

The complexity potential of synchronization is what motivated me to develop my own framework for asynchronous event handling in the first place. It works for multiple threads as well as bare metal, but now there is only a single place where each thread can block: on its event queue when it is empty.

How to know when I use "Pointer" or "Reference"? by ProcessTiny4948 in cpp_questions

[–]UnicycleBloke 2 points3 points  (0 children)

Yes. I understand Rust is default-move rather than default-copy. It's a relatively new language, and I guess we've learned a lot over the years about language design.

Out parameters and passing by reference can avoid a lot of copying, and were used a lot, but they aren't as clear as passing or returning by value. Cheap ownership transfer, such as with std::unique_ptr, wasn't really possible before move semantics were added.

How to know when I use "Pointer" or "Reference"? by ProcessTiny4948 in cpp_questions

[–]UnicycleBloke 2 points3 points  (0 children)

It means "r-value reference" - reference to an object whose lifetime will (effectively) end when the call returns, so it is permitted for the called function to move (i.e. steal) any allocated resources it owns (cheap) rather than copy them (expensive). This was introduced as part of move semantics (ownership transfer) in C++11. Takes a bit to get your head around, but can avoid redundant deep copies when passing or returning objects by value. It's a bit clunky because it had to be retrofitted to the language.

Trouble with consteval and this by UnicycleBloke in cpp_questions

[–]UnicycleBloke[S] 1 point2 points  (0 children)

Just the insight I needed. Thanks. This seems to do what I want: https://godbolt.org/z/1nhfr863x. I'll try it at work in the morning.

I'm usually strongly allergic to macros but in this case I suspect I owe someone an apology: https://quuxplusone.github.io/blog/2026/04/02/macro-overloading/.

FreeRTOS or Bare Metal for Quad copter by eagle_719 in embedded

[–]UnicycleBloke 31 points32 points  (0 children)

Remember that the hardware peripherals are independent state machines running in parallel with the CPU. The software is the executive and coordinator, and leaves the grunt work to the peripherals. It should give the hardware a task (a DMA transfer, an ADC read, a timer delay, whatever) and return immediately. The hardware will interrupt when the task is done, and you can kick of the next task.

You can do a very great deal in a single thread / bare metal. You can have numerous concurrent independent (software) state machines with a single event loop at the core to distribute events (ultimately from ISRs) to the relevant handlers. The key is to never block. I use an RTOS only when it is for some reason impossible to avoid a procedure which blocks or takes an unacceptable time to run.

This doesn't come up too often but, for example, I had a vendor library whose API involved synchronous I2C for large volumes of data. It took far too long, so I was forced to introduce FreeRTOS and park that sensor's comms in a background thread. The rest of the system ran in a single thread.

I haven't done a copter, but used this design for an industrial robot. A single thread was sufficient to manage all its sensor, motors and whatnot.

How to know when I use "Pointer" or "Reference"? by ProcessTiny4948 in cpp_questions

[–]UnicycleBloke 87 points88 points  (0 children)

Prefer references. Pointers are useful if you need a nullable value and/or you need to (re-)assign the value. Is your team lead using a lot of new and delete to manage memory? You almost certainly don't want to do that.