Trusted Software Excellence across Desktop and Embedded
Take a glance at the areas of expertise where KDAB excels ranging from swift troubleshooting, ongoing consulting and training to multi-year, large-scale software development projects.
Find out why customers from innovative industries rely on our extensive expertise, including Medical, Biotech, Science, Renewable Energy, Transportation, Mobility, Aviation, Automation, Electronics, Agriculture and Defense.
High-quality Embedded Engineering across the Stack
To successfully develop an embedded device that meets your expectations regarding quality, budget and time to market, all parts of the project need to fit perfectly together.
Learn more about KDAB's expertise in embedded software development.
Where the capabilities of modern mobile devices or web browsers fall short, KDAB engineers help you expertly architect and build high-functioning desktop and workstation applications.
Extensible, Safety-compliant Software for the Medical Sector
Create intelligent, patient-focused medical software and devices and stay ahead with technology that adapts to your needs.
KDAB offers you expertise in developing a broad spectrum of clinical and home-healthcare devices, including but not limited to, internal imaging systems, robotic surgery devices, ventilators and non-invasive monitoring systems.
Building digital dashboards and cockpits with fluid animations and gesture-controlled touchscreens is a big challenge.
In over two decades of developing intricate UI solutions for cars, trucks, tractors, scooters, ships, airplanes and more, the KDAB team has gained market leading expertise in this realm.
Build on Advanced Expertise when creating Modern UIs
KDAB assists you in the creation of user-friendly interfaces designed specifically for industrial process control, manufacturing, and fabrication.
Our specialties encompass the custom design and development of HMIs, enabling product accessibility from embedded systems, remote desktops, and mobile devices on the move.
Legacy software is a growing but often ignored problem across all industries. KDAB helps you elevate your aging code base to meet the dynamic needs of the future.
Whether you want to migrate from an old to a modern GUI toolkit, update to a more recent version, or modernize your code base, you can rely on over 25 years of modernization experience.
KDAB offers a wide range of services to address your software needs including consulting, development, workshops and training tailored to your requirements.
Our expertise spans cross-platform desktop, embedded and 3D application development, using the proven technologies for the job.
When working with KDAB, the first-ever Qt consultancy, you benefit from a deep understanding of Qt internals, that allows us to provide effective solutions, irrespective of the depth or scale of your Qt project.
Qt Services include developing applications, building runtimes, mixing native and web technologies, solving performance issues, and porting problems.
KDAB helps create commercial, scientific or industrial desktop applications from scratch, or update its code or framework to benefit from modern features.
Discover clean, efficient solutions that precisely meet your requirements.
Boost your team's programming skills with in-depth, constantly updated, hands-on training courses delivered by active software engineers who love to teach and share their knowledge.
Our courses cover Modern C++, Qt/QML, Rust, 3D programming, Debugging, Profiling and more.
The collective expertise of KDAB's engineering team is at your disposal to help you choose the software stack for your project or master domain-specific challenges.
Our particular focus is on software technologies you use for cross-platform applications or for embedded devices.
Since 1999, KDAB has been the largest independent Qt consultancy worldwide and today is a Qt Platinum partner. Our experts can help you with any aspect of software development with Qt and QML.
KDAB specializes in Modern C++ development, with a focus on desktop applications, GUI, embedded software, and operating systems.
Our experts are industry-recognized contributors and trainers, leveraging C++'s power and relevance across these domains to deliver high-quality software solutions.
KDAB can guide you incorporating Rust into your project, from as overlapping element to your existing C++ codebase to a complete replacement of your legacy code.
Unique Expertise for Desktop and Embedded Platforms
Whether you are using Linux, Windows, MacOS, Android, iOS or real-time OS, KDAB helps you create performance optimized applications on your preferred platform.
If you are planning to create projects with Slint, a lightweight alternative to standard GUI frameworks especially on low-end hardware, you can rely on the expertise of KDAB being one of the earliest adopters and official service partner of Slint.
KDAB has deep expertise in embedded systems, which coupled with Flutter proficiency, allows us to provide comprehensive support throughout the software development lifecycle.
Our engineers are constantly contributing to the Flutter ecosystem, for example by developing flutter-pi, one of the most used embedders.
KDAB invests significant time in exploring new software technologies to maintain its position as software authority. Benefit from this research and incorporate it eventually into your own project.
Start here to browse infos on the KDAB website(s) and take advantage of useful developer resources like blogs, publications and videos about Qt, C++, Rust, 3D technologies like OpenGL and Vulkan, the KDAB developer tools and more.
The KDAB Youtube channel has become a go-to source for developers looking for high-quality tutorial and information material around software development with Qt/QML, C++, Rust and other technologies.
Click to navigate the all KDAB videos directly on this website.
In over 25 years KDAB has served hundreds of customers from various industries, many of them having become long-term customers who value our unique expertise and dedication.
Learn more about KDAB as a company, understand why we are considered a trusted partner by many and explore project examples in which we have proven to be the right supplier.
The KDAB Group is a globally recognized provider for software consulting, development and training, specializing in embedded devices and complex cross-platform desktop applications.
Read more about the history, the values, the team and the founder of the company.
When working with KDAB you can expect quality software and the desired business outcomes thanks to decades of experience gathered in hundreds of projects of different sizes in various industries.
Have a look at selected examples where KDAB has helped customers to succeed with their projects.
KDAB is committed to developing high-quality and high-performance software, and helping other developers deliver to the same high standards.
We create software with pride to improve your engineering and your business, making your products more resilient and maintainable with better performance.
KDAB has been the first certified Qt consulting and software development company in the world, and continues to deliver quality processes that meet or exceed the highest expectations.
In KDAB we value practical software development experience and skills higher than academic degrees. We strive to ensure equal treatment of all our employees regardless of age, ethnicity, gender, sexual orientation, nationality.
Interested? Read more about working at KDAB and how to apply for a job in software engineering or business administration.
C++23 is feature complete and on track to be released next year. While many people are complaining that it's, after all, a "minor" release (as the pandemic made the Committee work very difficult), C++23 still has a few very significant changes.
In this blog post, I want to talk about what I think is my favorite feature of C++23: thereally keyword. This is a brand new keyword that can be used in a number of different scenarios. Let's explore them together to understand the usefulness of it.
For Function Arguments
Consider a function like:
voidf(int x);
Unfortunately, we all know too well that C++ allows you to call it with non-integer arguments:
f(1234);// OK, intended: called with an intf(3.14);// Not really intended (called with double), still legal
If you're lucky, your compiler may give you a warning. Otherwise, the calls with non-int (double, long, ...) will be valid, and this may cause unexpected data losses and/or undefined behavior. Could it be possible to have a compile-time error instead?
While the C++20 version is a huge readability improvement over the SFINAE version, it's still a mouthful. Also, this makes the function a function template, so now it can't be out-of-line, it impacts our compilation times, etc.
In C++23 this will be possible by addingreally:
voidf(really int x);f(42);// OKf(3.14);// ERROR
Simple and effective! You can also apply it to ordinary variables or to return types:
really int i =getInt();// OKreally int j =getDouble();// ERROR
The compiler is doing something quite peculiar here: it's multiplying len by 42, calling a() with the result of the calculation, then it multiplies len again in order to call a() a second time. How come it's doing the same (relatively) expensive operation twice, rather than simply storing the result and using it for both calls? a() is a const member function, after all, so it can't change len -- or can it?
Well, the short answer is that the compiler is not allowed to do otherwise: the value of len could've been indeed changed by the call to a(). Maybe a() ends up calling something else, and that something else changes *this. Or maybe a() is just doing a const_cast<String *>(this) and then mutating the result. It doesn't change the result: the compiler is forced to reload the data members after a member function call as it can't assume that they haven't been changed. The fact that the target member function is const does not help the compiler in any way.
It may look longer, but we have a couple of extra mov in lieu of an imul. The multiplication result is stored and reused for the second call. And that's a huge win!
What really const does is makes the compiler consider a work on an object declared const. Such objects cannot be mutated, not even by stripping their constness away (that's undefined behavior). This causes better codegen; now the compiler knows that calling a cannot possibly mutate *this.
Closed Enumerations
Suppose you have an enumeration like this:
enumclassMyEnum{ E1, E2, E3
};
Now, suppose you have a function that takes a value of this enumeration. Correctly, you use a switch over the value, in order to handle all the possible cases:
Now, for some reason, your compiler will complain about calculate. Specifically written like this, you will get a warning regarding the possibility for control to reach the end of the function without hitting a return statement, and the function does not return void.
How in the world is that possible? There's clearly a switch in there that is covering all the possible enumerators!
Defeated, you'll change your function to something like this:
intcalculate(MyEnum e){switch(e){case MyEnum::E1:return42;case MyEnum::E2:return51;case MyEnum::E3:return123;// for the love of kittens, DO NOT add a default: !!!}assert(false);return-1;// impossible}
(Yes, do NOT add a default: to the switch -- a default label will prevent the compiler from warning you that the switch is no longer covering all the enumerators, should you decide some day to extend the enumeration.)
So how is "the impossible" actually possible? Is the compiler wrong?
No, the compiler is right. There is the possibility of passing a value which isn't handled by the switch; and that's because C++ allows casting integers to enumerations, as long as the integer "fits" in the enumerator's range. See the wording in [expr.static.cast]:
That means that this is 100% legal C++:
voidbad(){ MyEnum nonsense =static_cast<MyEnum>(-1);int result =calculate(nonsense);// whops!}
But just how often is this feature really useful? While, in general, allowing conversions from integer to enumerations makes sense, people are not really supposed to cast arbitrary integers into an enumeration's type.
Enterreally enum, or, of course, enum really as it needs to be spelled:
enumclassreally MyEnum { E1, E2, E3
};intcalculate(MyEnum e){switch(e){case MyEnum::E1:return42;case MyEnum::E2:return51;case MyEnum::E3:return123;}// no warning, all cases are handled}voidbad(){ MyEnum nonsense =static_cast<MyEnum>(-1);// UB, -1 is not an enumerator}
Basically, a really enum is just like an ordinary enum (or enum class, like in this case), except that converting integers to it requires the integer to match the value of one of the enumerators -- otherwise, undefined behavior. The UB is not really worse than what we had before (walking out of a function without returning) or crashing due to the failed assert. On top if that, thanks to things like ubsan, we can catch the problem (= the illegal conversion) at its source rather than later, when it causes havok.
For Deduced rvalue References
Let's face it: templates arehard. And deduction rules for function templates, combined with value categories, are even harder!
But let's start with a simple example. Any proficient C++ developer should know that it's possible to overload a function f for lvalues and rvalues:
Now suppose you want to make your f generic, so it can work on std::string but also on other string types. That, of course, means turning f into a function template.
Easy enough, right? Well, raise your hand if you ever fell into this trap:
template<typenameT>voidf(const T &obj);// 1) lvalue referencetemplate<typenameT>voidf(T &&obj);// 2) rvalue reference...?
The double ampersand still means rvalue reference, doesn't it? Turns out that, well, yes, but actually no. Since T is deduced, it doesn't; it now means forwarding (or universal) reference. This code:
std::string s ="hello";f(s);// call f on a lvalue
is now actually calling overload n. 2 (!!!), after deducing T = std::string &.
This is incredibly annoying and error-prone: the very same syntax, without deduced template arguments, works correctly. Reusing the same syntax with totally different meanings is a major annoying point (just think about the teachability of such a feature...).
In order to force the second overload only to take rvalue references, we have to again deploy SFINAE or similar techniques:
template<typenameT>voidf(const T &obj);// lvalue referencetemplate<typenameT> std::enable_if_t<!std::is_reference_v<T>>f(T &&obj);// T must not be a reference => T&& is a rvalue reference
I mean... really?! (pun intended) I bet that if we had a time machine, someone would surely propose the usage of different syntax (a triple ampersand?) to specify forwarding references and remove the entire problem.
Luckily for us, in C++23, we can do this:
template<typenameT>voidf(const T really &obj);// 1) lvalue referencetemplate<typenameT>voidf(T really &&obj);// 2) rvalue reference! not forwarding reference
This brings back the "traditional" rules without any of the verbose SFINAE syntax. Technically speaking, it's not needed on 1), but I like the symmetry.
Really Operator Auto
A problem that sometimes affects Qt users is the following:
QString getString();voidprint(QString);voidf(){auto result =QString("The result is: ")+getString();print(result);}
What's the type ofresult? You may think it's a QString -- after all, it's being obtained by concatenating (via operator+) two QString objects.
That's actually correct in some cases, but in (many) others, it's not accurate. Generally speaking, result is actually an object of type QStringBuilder.
What'sQStringBuilder, you ask? It's a private class in Qt that is employed to optimize string concatenations. A concatenation like this:
QString a, b, c, d;QString result = a + b + c + d;
may cause up to 3 memory allocations, if done naively: first, calculate a + b (allocate); then, append c to the result (allocate again); then, append d to the final result (allocate again).
QStringBuilder instead considers the entire "sequence" of operations. When QStringBuilder is in use, a + b does not return a QString directly. It returns a QStringBuilder that remembers a and b (It simply internally stores references to them). Note that no allocations (for the result) or copies are taking place yet.
Then, appending c to the intermediate QStringBuilder yields anotherQStringBuilder that now remembers c, too. Finally, d is appended, yielding one final QStringBuilder.
This final object is then converted to a QString. That's where the magic kicks in: QStringBuilder can now perform one memory allocation of the right size (by asking all the other strings about their sizes, as it's keeping references to all of them), copy their contents in order to perform the concatenation, and produce result.
So what's wrong in the first example? The answer is the usage of auto:
auto result =QString("The result is: ")+getString();// whops!
Here, a QStringBuilder is produced in order to concatenate the two strings. But it's never converted to a QString. Instead, result is an object of type QStringBuilder itself!
That is a problem because, as mentioned before, QStringBuilder merely references the strings that it is supposed to concatenate. These strings are temporaries that will get destroyed at the end of the statement. That means that we now have a QStringBuilder loaded with dangling references!
Again, with a time machine, the solution could be to allow like this:
classQStringBuilder{// invoked when assigning the result to `auto` variable...?operatorauto()const{returnQString(*this);}};
Although operator auto() exists, it's not what the comment above says. operator auto is nothing but an "ordinary" conversion operator, combined with auto deduction for the return type of a function. In other words, the above is just declaring an operator QString() const -- but we already have that one inside QStringBuilder!
Instead, in C++23 we can do this:
classQStringBuilder{// invoked when assigning the result to `auto` variable. really operatorauto()const{returnQString(*this);}};
Note that the position of really is important. Otherwise, it applies to the conversion target type, just like I've shown before:
classC{operator really int()const;};C c;int i = c;// OKdouble d = c;// ERROR
And that's it! I hope you liked this little presentation about the new keyword. I can't wait to start working on C++23 projects to try this one out (and also the other goodies, which you can check out on cppreference).
Trusted software excellence across embedded and desktop platforms
The KDAB Group is a globally recognized provider for software consulting, development and training, specializing in embedded devices and complex cross-platform desktop applications. In addition to being leading experts in Qt, C++ and 3D technologies for over two decades, KDAB provides deep expertise across the stack, including Linux, Rust and modern UI frameworks. With 100+ employees from 20 countries and offices in Sweden, Germany, USA, France and UK, we serve clients around the world.
This is really great news! Really hope it really happens.
1 - Apr - 2022
Bart
Happy April's Fools.
1 - Apr - 2022
Soroush Rabiei
In the last committee meeting, I remember someone suggested renaming 'really' to 'indeed'. I hope this will be approved before next April.
1 - Apr - 2022
RJ
You're missing the "honestly" proposal. Unlike really, honestly would also allow conversions between types that sound different but are honestly the same, in behavior and layout.
For example, on a MS Windows machine, a long int is honestly an int.
This would also allow conversions from char8_t, which is honestly an unsigned char.
Both "really" and "honestly" could coexist. And honestly, really and honestly would be nice to have.
1 - Apr - 2022
Yacob Cohen-Arazi
I hate this date! ;)
2 - Apr - 2022
nyanpasu64
Basically, a really enum is just like an ordinary enum (or enum class, like in this case), except that converting integers to it requires the integer to match the value of one of the enumerators — otherwise, undefined behavior.
Well that's already the case since MyEnum doesn't have a fixed underlying type (: int), as ubsan impolitely pointed out to me one day when casting a bit flag to an enum.
2 - Apr - 2022
Giuseppe D'Angelo
Well that’s already the case since MyEnum doesn’t have a fixed underlying type (: int), as ubsan impolitely pointed out to me one day when casting a bit flag to an enum.
Each enumeration also has an underlying type.
The underlying type can be explicitly specified using an enum-base.
For a scoped enumeration type, the underlying type is int if it is not explicitly specified.
In both of these cases, the underlying type is said to be fixed.
9 - Apr - 2022
alagner
Didn't you mean std::enable_if_t<!std::is_lvalue_reference_v> instead of std::enable_if_t<!std::is_reference_v>?
10 - Apr - 2022
Giuseppe D'Angelo
Well spotted, and, pedantically, yes -- although usually the idea is to let the template type argument to be deduced (most things, like the std algorithms, don't want users to specify the template arguments).
8 - May - 2022
LorenDB
Now I want this to be a thing. A really keyword would be really (ha!) infinitely handy.
22 - Jun - 2022
Sebastian
Shouldn't syntax highlighting be improved so that 'really' is coloured as a keyword?
22 - Jun - 2022
Giuseppe D'Angelo
Absolutely. It already does, but it works only on April 1st, 2023...
Giuseppe D’Angelo
Senior Software Engineer
Senior Software Engineer at KDAB. Giuseppe is a long-time contributor to Qt, having used Qt and C++ since 2000, and is an Approver in the Qt Project. His contributions in Qt range from containers and regular expressions to GUI, Widgets, and OpenGL. A free software passionate and UNIX specialist, before joining KDAB, he organized conferences on opensource around Italy. He holds a BSc in Computer Science.
Our hands-on Modern C++ training courses are designed to quickly familiarize newcomers with the language. They also update professional C++ developers on the latest changes in the language and standard library introduced in recent C++ editions.
12 Comments
1 - Apr - 2022
RJ
This is really great news! Really hope it really happens.
1 - Apr - 2022
Bart
Happy April's Fools.
1 - Apr - 2022
Soroush Rabiei
In the last committee meeting, I remember someone suggested renaming 'really' to 'indeed'. I hope this will be approved before next April.
1 - Apr - 2022
RJ
You're missing the "honestly" proposal. Unlike really, honestly would also allow conversions between types that sound different but are honestly the same, in behavior and layout.
For example, on a MS Windows machine, a long int is honestly an int.
This would also allow conversions from char8_t, which is honestly an unsigned char.
Both "really" and "honestly" could coexist. And honestly, really and honestly would be nice to have.
1 - Apr - 2022
Yacob Cohen-Arazi
I hate this date! ;)
2 - Apr - 2022
nyanpasu64
Well that's already the case since MyEnum doesn't have a fixed underlying type (: int), as ubsan impolitely pointed out to me one day when casting a bit flag to an enum.
2 - Apr - 2022
Giuseppe D'Angelo
MyEnum does in fact have a fixed underlying type because it's a scoped enumeration. See https://eel.is/c++draft/dcl.enum#5:
9 - Apr - 2022
alagner
Didn't you mean
std::enable_if_t<!std::is_lvalue_reference_v>
instead ofstd::enable_if_t<!std::is_reference_v>
?10 - Apr - 2022
Giuseppe D'Angelo
Well spotted, and, pedantically, yes -- although usually the idea is to let the template type argument to be deduced (most things, like the std algorithms, don't want users to specify the template arguments).
8 - May - 2022
LorenDB
Now I want this to be a thing. A
really
keyword would be really (ha!) infinitely handy.22 - Jun - 2022
Sebastian
Shouldn't syntax highlighting be improved so that 'really' is coloured as a keyword?
22 - Jun - 2022
Giuseppe D'Angelo
Absolutely. It already does, but it works only on April 1st, 2023...