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.
Here at KDAB, we recently published a library called KDBindings, which aims to reimplement both Qt signals and slots and data binding in pure C++17.
To get an introduction to the KDBindings implementation of signals and slots, I recommend that you take a look at the KDBindings Getting Started Guide. It will give you an overview of what signals and slots are, as well as how our implementation of them is used. Alternatively, take a look at our introductory blog post.
On a basic level, signals model an event that might occur, like a command being issued or a variable being set. The signal will then "emit" the data associated with the event. This data is the signal's "signature," similar to a normal function signature. The signal can then be connected to any function with a matching signature. Such functions are referred to as "slots." Whenever the signal is emitted, it will call all of these slots in an arbitrary order. They can then react to the event.
Because this mechanism is very well-suited to loosely couple different systems, we discovered that it is often useful to connect a signal to a slot, even if their signatures only partially match.
This is especially useful if the signature of the signal was not designed to explicitly work together with this particular slot, but rather to be generic. Signals might emit too much information, for example, when a slot is only interested in the occurrence of an event and not the data associated with it. On the other hand, a slot might require additional information that is not emitted by the signal but might be available when the slot is connected.
Commands and Titles
Let's say we have a Signal<std::string, std::chrono::time_point<std::chrono::system_clock>> that is emitted every time the user issues a command. The std::string that is emitted contains the command issued and the time_point contains the timestamp of when the command was issued.
Now imagine that we want to update the title of our application so that it always displays the last issued command.
Ideally, we would want to be able to write something like this to make that happen:
classWindow{public:voidsetTitle(const std::string& title){...}};// This Signal would be emitted every time the user issues a commandSignal<std::string, std::chrono::time_point<std::chrono::system_clock>> commandSignal;Window appWindow;commandSignal.connect(&Window::setTitle,&appWindow);
Unfortunately, this won't just work immediately. The connect function on the signal needs to do a lot of work here:
Window::setTitle is a member function, so it will need a this pointer to the object it should modify. In this case, this is &appWindow.
The function doesn't have any use for the time_point emitted by the signal, only for the std::string. So, the signal must discard its second argument for this particular slot.
std::bind Function Pointer as a Workaround
The problem is that the default implementation of the connect function only takes a "std::function<void(std::string, std::chrono::time_point<std::chrono::system_clock>)>" as its argument.
A workaround for this could be the use of std::bind:
With this, we can provide our member function with the required pointer to our appWindow. Furthermore, std::bind returns an object that can be called with a basically unlimited number of arguments. Since we only used std::placeholders::_1, it will then discard all arguments except the first one. In our case, this would discard the time_point argument, which is exactly what we need.
In general, using std::bind would work. However, the previously shown API would be a lot nicer, as it hides the std::bind call and doesn't require the use of any placeholders.
Let's use template meta-programming to write a function that can generate the needed call to std::bind for us.
The bind_first Function
Our initial goal is to create a function that, similar to std::bind, can bind arguments to a function. However, for our use case, we only want to bind the first arguments and refrain from explicitly specifying the placeholders for every remaining argument.
For the general idea of how to solve this problem, I found a Github Gist that defines a function bind_first that almost does what we need. It can generate the needed placeholders for std::bind as well as forward the arguments to be bound.
The problem with this implementation is that it uses sizeof...(Args) to determine how many placeholders need to be generated. The Args variadic template argument is only available because it requires the function to be a non-const member function. So, this won't work on just any function type. It won't even work on const member functions.
However, if we assume there is a compile-time function get_arity that returns the arity (number of arguments) of a function, we can improve bind_first to accept any function type:
// We create a template struct that can be used instead of std::placeholders::_X.// Then we can use template-meta-programming to generate a sequence of placeholders.template<int>structplaceholder{};// To be able to use our custom placeholder type, we can specialize std::is_placeholder.namespace std {template<int N>structis_placeholder<placeholder<N>>: integral_constant<int, N>{};};// namespace std// This helper function can then bind a certain number of arguments "Args",// and generate placeholders for the rest of the arguments, given an// index_sequence of placeholder numbers.//// Note the +1 here, std::placeholders are 1-indexed and the 1 offset needs// to be added to the 0-indexed index_sequence.template<typenameFunc,typename... Args, std::size_t... Is>autobind_first_helper(std::index_sequence<Is...>, Func &&fun, Args... args){return std::bind( std::forward<Func>(fun), std::forward<Args>(args)..., placeholder<Is +1>{}...);}// The bind_first function then simply generates the index_sequence by// subtracting the number of arguments the function "fun" takes, with// the number of arguments Args, that are to be bound.template<typenameFunc,typename... Args,/*
Disallow any placeholder arguments, they would mess with the number
and ordering of required and bound arguments, and are, for now, unsupported
*/typename= std::enable_if_t< std::conjunction_v<std::negation<std::is_placeholder<Args>>...>>>autobind_first(Func &&fun, Args &&...args){returnbind_first_helper( std::make_index_sequence<get_arity<Func>()-sizeof...(Args)>{}, std::forward<Func>(fun), std::forward<Args>(args)...);}// An example use:QWindow window;std::function<void(QString, std::chrono::time_point<std::chrono::system_clock>)> bound =bind_first(&QWindow::setTitle,&window);
The get_arity Function
As noted earlier, the bind_first implementation assumes the existence of a get_arity function, which can determine the number of arguments of a function at compile time.
This function is, however, not part of standard C++. So, how does one go about implementing it?
In comparison to the StackOverflow answer, I chose to implement this using a constexpr function, as I find the interface clearer when called.
Without further ado, here's the code:
// This is just a template struct necessary to overload the get_arity function by type.// C++ doesn't allow partial template function specialization, but we can overload it with our tagged type.template<typenameT>structTypeMarker{constexprTypeMarker()=default;};// Base implementation of get_arity refers to specialized implementations for each// type of callable object by using the overload for it's specialized TypeMarker.template<typenameT>constexpr size_t get_arity(){returnget_arity(TypeMarker<std::decay_t<T>>{});}// The arity of a function pointer is simply it's number of arguments.template<typenameReturn,typename... Arguments>constexpr size_t get_arity(TypeMarker<Return(*)(Arguments...)>){returnsizeof...(Arguments);}template<typenameReturn,typename... Arguments>constexpr size_t get_arity(TypeMarker<Return(*)(Arguments...)noexcept>){returnsizeof...(Arguments);}// The arity of a generic callable object is the arity of it's operator() - 1,// as the "this" pointer is already known for such an object.// As lambdas are also just instances of an anonymous class, they must also implement// the operator() member function, so this also works for lambdas.template<typenameT>constexpr size_t get_arity(TypeMarker<T>){returnget_arity(TypeMarker<decltype(&T::operator())>{})-1;}// Syntactic sugar version of get_arity, allows passing any callable object// to get_arity, instead of having to pass its decltype as a template argument.template<typenameT>constexpr size_t get_arity(const T &){returnget_arity<T>();}
This code will work for free functions. It also works for arbitrary objects that implement the function call operator (operator()) by delegating to the get_arity function for that operator() member function. This also includes lambdas, as they must implement the function call operator as well.
Unfortunately, implementing get_arity for member functions is a bit more complicated.
This works well for normal, plain member functions. What about const-correctness though?
We would need another overload for TypeMarker<Return (Class::*)(Arguments...) const>. Taking a look at the cppreference for function declarations reveals that we also need to take care of volatile, noexcept, as well as ref qualified (& and &&) member functions.
Unfortunately, I have not found any way to remove these specifiers from the function pointer types that are already available. But instantiating every combination isn't too bad when we use a macro to do the heavy lifting for us:
// remember to add +1, the "this" pointer is an implicit argument#defineKDBINDINGS_DEFINE_MEMBER_GET_ARITY(MODIFIERS)template<typenameReturn,typenameClass,typename... Arguments>\constexpr size_t get_arity(TypeMarker<Return(Class::*)(Arguments...) MODIFIERS>)\{\returnsizeof...(Arguments)+1;\}KDBINDINGS_DEFINE_MEMBER_GET_ARITY()KDBINDINGS_DEFINE_MEMBER_GET_ARITY(const)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(&)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(const&)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(&&)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(const&&)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatile)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatileconst)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatile&)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatileconst&)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatile&&)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatileconst&&)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(noexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(constnoexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(&noexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(const&noexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(&&noexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(const&&noexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatilenoexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatileconstnoexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatile&noexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatileconst&noexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatile&&noexcept)KDBINDINGS_DEFINE_MEMBER_GET_ARITY(volatileconst&&noexcept)
So it's a macro to generate template functions, which are pretty much macros themselves -- that's a lot of meta programming.
But in the end, we are successful. This code will work for (almost) any callable object. The current limits I can think of are overloaded functions as well as template functions. These have to be disambiguated, as it's not clear which overload get_arity should refer to.
The definition of get_arity might especially come in handy in the future, if further metaprogramming with arbitrary callable objects is needed.
Putting It All Together
With our completed bind_first implementation, we can now define a new connect function for our signal:
// We use the enable_if_t here to disable this function if the argument is already// convertible to the correct std::function typetemplate<typenameFunc,typename... FuncArgs>autoconnect(Func &&slot, FuncArgs &&...args)const-> std::enable_if_t< std::disjunction_v< std::negation<std::is_convertible<Func, std::function<void(Args...)>>>,/* Also enable this function if we want to bind at least one argument*/ std::integral_constant<bool,sizeof...(FuncArgs)>>, ConnectionHandle
>{returnconnect(static_cast<std::function<void(Args...)>>(bind_first(std::forward<Func>(slot), std::forward<FuncArgs>(args)...)));}
As mentioned earlier, this also allows us to bind functions to a signal that need additional information.
Signal<std::string, std::chrono::time_point<std::chrono::system_clock>> commandSignal;
// Imagine we had a logging function that takes a logging level
// and a message to log.
void log(const LogLevel& level, const std::string& message);
// Connecting this function will now log the user command every time
// with the log level "Info".
commandSignal.connect(log, LogLevel::Info);
All of these features come together to make KDBindings signals very flexible in how they can connect to signals. That makes it very easy to couple together systems without having to make the signals and slots entirely line up first.
KDBindings
If you want to check out the complete code, take a look at the KDBindings source on Github.
The library also offers a lot more awesome features, like properties and data binding in pure C++17. It's a header-only library that is easy to integrate and licensed with the very liberal MIT-License.
This, of course, also means that you're free to use the code shown here however you like.
About KDAB
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.
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.