stephan beal <stephan@s11n.net>
This paper covers the use of type-based contexts in C++. It is targetted at intermediate-to-advanced C++ programmers.
The entire content of this article is released into the Public Domain.
Most programmers are familiar with the concept of resource handles. To recap: what is a resource handle? It is a unique identifier which identifies some type of resource within a system. The most common example is probably C's classic file handles, which one uses to pass to functions like fclose(), so that fclose() knows which file it is really supposed to close. Handles come in a variety of flavours, but the are invariably used to define the context within which a given set of operations is performed. e.g., fclose(myhandle) instructs fclose() to only close the file associated with myhandle, and not another file.
This paper takes the concept of resource handles a step further, defining ''type handles'', or what we will refer to as Context Types. In short, a context type is an arbitrary type which is used to limit certain operations to a scope - the scope of the given context. Clear as mud? The rest of this paper will try to make clear what exactly context types are, how to implement them, and how they can be used to add flexibility to some otherwise-inflexible code.
C++'s template facilities offer a different type of handle, vaguely related to classic resource handles but based, instead of on runtime-mutable values, on types.
Jumping right in... here we show a trivial example of how type-based contexts can be used to genericize a very simple function. Consider the following function, who's sole purpose is to dole out a new number each time it is called:
size_t next_id() {static size_t bob;
Seems straightforward enough, right? Now we're going to make a trivial change to make this function dole out unique IDs based on contexts. Rather than explain what we're going to do, the one-line code difference says it all:return ++bob;}
template <typename ContextType>
size_t next_id() {static size_t bob;
Let's quickly go over the implications of this one-line change:return ++bob;}
The above simple example only touches on the potential uses of context types. We'll spend the rest of the paper trying to convince you that context types are useful in a variety of ... well, contexts.
We said above that context types are conceptually similar to resource handles. How is that so? Consider: when calling next_id() with different context types we are essentially giving the function a different resource handle, i.e. a different context in which to perform it's work. In doing so we assure that next_id<X>() and next_id<Y>() do not interfere with each other.
Let's consider this classic example of implementing what are often dubbed Meyers Singletons, after the programming god Scott Meyers, who reportedly first published this approach:
template <typename T>
struct MeyersSingleton {typedef T singleton_type;
singleton_type & instance() {static singleton_type bob;
Pretty straightforward. Now, as we did with the next_id() function, we're now going to make a minor change:};return bob;}
template <typename T, typename ContextType = T>
struct MeyersSingleton {As before, we haven't had to change the internals of our code, but the implications of this subtle change anything but subtle. We now have what i often call ''context singletons'':... same implementation as above ...};
MyType & m1 = MeyersSingleton<MyType>::instance();
MyType & m2 = MeyersSingleton<MyType,int>::instance();Those two calls return different objects. Rather than use a POD, such as int, to define a context it is often useful to define no-op marker classes, such as this one:
struct my_sharing_context {};Using this approach we can more easily control which contexts are used (as opposed to inadvertently abused) by other code. Keep in mind that typedefs do not define new types, so the following does not define a new context:
typedef int my_sharing_context;
This paper has only briefly covered a small number of uses for context types. They have a wide variety of uses not covered here, and i'm quite certain that anyone who has found this paper worth reading will be able to quickly come up with their own ideas for utilizing context types in their projects.
This paper os a more general refinement of a larger (and older) paper on this topic, entitled Context Singletons, available from:
http://s11n.net/papers/That paper extends the idea of Context Singletons, providing, e.g., a client-agnostic way of populating shared objects upon their first instantiation via a functor.
This document was generated using the LaTeX2HTML translator Version 2002-2-1 (1.70)
Copyright © 1993, 1994, 1995, 1996,
Nikos Drakos,
Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999,
Ross Moore,
Mathematics Department, Macquarie University, Sydney.
The command line arguments were:
latex2html -no_subdir -split 0 -show_section_numbers /tmp/lyx_tmpdir13071L2d4UF/lyx_tmpbuf1/context_types.tex
The translation was initiated by stephan on 2004-06-14