CALLBACKS IN C++ USING TEMPLATE FUNCTORS
Copyright 1994 Rich Hickey
INTRODUCTION
One of the many promises of Object-Oriented programming is that it will allow for plug-and-play software design with re-usable components. Designers will pull objects from their library 'shelves' and hook them together to make software. In C++, this hooking together of components can be tricky, particulary if they are separately designed. We are still a long way from interoperable libraries and application components. Callbacks provide a mechanism whereby independently developed objects may be connected together. They are vital for plug and play programming, since the likelihood of Vendor A implementing their library in terms of Vendor B's classes, or your home-brewed classes, is nil.
Callbacks are in wide use, however current implementations differ and most suffer from shortcomings, not the least of which is their lack of generality. This article describes what callbacks are, how they are used, and the criteria for a good callback mechanism. It summarizes current callback methods and their weaknesses. It then describes a flexible, powerful and easy-to-use callback technique based on template functors - objects that behave like functions.
CALLBACK FUNDAMENTALS
What Are Callbacks?
When designing application or sub-system specific components we often know all of the classes with which the component will interact and thus explicity code interfaces in terms of those classes. When designing general purpose or library components however, it is often necessary or desirable to put in hooks for calling unknown objects. What is required is a way for one component to call another without having been written in terms of, or with knowledge of, the other component's type. Such a 'type-blind' call mechanism is often referred to as a callback.
A callback might be used for simple notification, two-way communication, or to distribute work in a process. For instance an application developer might want to have a Button component in a GUI library call an application-specific object when clicked upon. The designer of a data entry component might want to offer the capability to call application objects for input validation. Collection classes often offer an apply() function, which 'applies' a member function of an application object to the items they contain.
A callback, then, is a way for a component designer to offer a generic connection point which developers can use to establish communication with application objects. At some subsequent point, the component 'calls back' the application object. The communication takes the form of a function call, since this is the way objects interact in C++.
... continue reading