Two types are named conformant if they share the same name. The significance of this is that types related by inheritance share the same name, that of their common base class. Consider the following class hierarchy:

This is nothing surprising (or at least it shouldn't be to any C++ programmer). It works because classes B, C, and D are all (publicly) derived from A, and because A::getName() is declared virtual. Thus, invocation of getName() on a given object reference (or pointer) depends not on the type of the reference (or pointer) but on the actual type of the object being referenced. This is known as Virtual Function Polymorphism, or Runtime Polymorphism or as just Polymorphism. (The latter, unqualified, name is no longer popular, for reasons that will become clear later in this document. Runtime Polymorphism is the recommended term, since it precisely describes what is going on: that the type is determined at runtime.)

We can say: Classes B, C and D exhibit named conformance with A.

So far so good.

Now assume that we want to write a function that will elicit the Id of instance of class B (or its derived classes):

What should also be understood is that we equally cannot apply printClassId() to an instance of C. Even though C has a getId() method, it is not derived from B, and thus is not compatible: it has a different name.

Hence: Class C, is not named conformant with B.

Put another way, the definition of printClassId() imposes the constraint on any type to which we wish to apply it that it must be named-conformant with B.

To display the Id from C we'd have to overload the printClassId() function:

Two types are structurally conformant if instances of them can be placed in syntactically identical constructs and exhibit (appropriately) similar semantics. In other words, they can both compile in the same code and will operate in the same (or suitably similar) manner.

Before we start, it's sensible to concede that, absent pre-processor acrobatics, structural conformance is primarily relevant when using templates.

The template parameter T is used in the function signature, as (part of) the type of the object parameter.

No part of the function template definition mentions the actual type of the parameter. What is mentioned, however, is that a (a non-mutating reference to) an instance of T has a member getId which can be involved in a function call expression and, further, that the result of that expression can be used with std::cout and std::endl via the insertion operator.

(Note: what may seem relatively obvious syntax above can actually be quite involved and surprising. For example, getId() could be a static method, or could be a member variable of a type that has a function call operator defined. Sometimes things can be even more exotic, involving enumerations and properties. The issue is discussed in greater depth in the chapter "Duck and Goose" from the forthcoming book Extended STL.)

This version of printClassId() is compatible with instances of B and D, and also with C.

Thus we can state: Classes B, C and D are structurally conformant with respect to printClassId().

Note the difference in emphasis in this statement. First, we describe this in terms of a mutual conformance between the conformant types, as opposed to a relative conformance in the case of named conformance. Second, we define their structural conformance in terms of the requirements of a constraining component, in this case the function template printClassId(). Further, it is important to understand that the enforced constraints of the constraining component are entirely syntactic. Naturally, there is an expectation that syntatically conformant types will also have the semantic conformance, but this is not something that the C++ language can enforce for us. Rather, we need to observe higher level conventions, such as member/method naming conventions.

Note:

There are mechanisms for explicit conformance, such as Shims, Concept Tagging and Member Type Tagging, but these are outside the scope of the current discussion. (See Extended STL for more details.)

As discussed above, structural conformance is the correspondence between syntax and semantics for unrelated types, for a given syntactic context (or set of contexts).

When designing facades one continually meets the challenge of abstracting common functionality between disparate technologies/APIs. Operating systems APIs are a very good example of this.

Consider that we want to provide a facade over the Windows mutex kernel object. Like most Windows kernel objects, the mutex may, optionally, be named to facilitate sharing between processes, and/or carry security attributes. They may be created already in the 'acquired' state. They are always recursive (which is to say that a thread that owns a mutex may 'acquire' it again).

The WinSTL project defines the facade winstl::process_mutex, which has the following class interface (explicit constructor qualifiers are not shown for clarity):

Now we want to provide a corresponding facade for the PThreads mutex (pthread_mutex_t). Unlike the Windows kernel object, PThreads' mutexes may not be named and do not support (Windows-like) security information. They do allow sharing, but in a much different (and largely) incompatible way to Windows: the mutex must be created as shareable, and is shared between processes via shared memory, rather than by accessing a kernel handle as in Windows.

The UNIXSTL project defines the facade unixstl::process_mutex, which has the following class interface (explicit constructor qualifiers are not shown for clarity):

In this approach functionality present in one interface that is missing in the other is emulated. For example, we could emulate the winstl::process_mutex::wait(DWORD) method for unixstl::process_mutex by using a retry loop and a micro_sleep() operation.

However, such approaches can be ugly, or unsafe, or inefficient, and are often all three. Furthermore, there are many cases where no meaningful analogue functionality can be specified. For example, we cannot incline the Windows mutex kernel object to reject recursive acquisition to be in line with the PThreads version. Nor can we apply the equivalent of Windows security information to a PThreads mutex. These things are, to all intents and purposes, impossible.

Given an impossibility of emulating missing functionality for a given facade, one might think that the only reasonable approach is to provide only what functionality is, or can be readily made to be, common to both. In the case of the process_mutex, this would yield class interfaces as follows:

This is useful, to be sure, but Windows users may find themselves needing to be able to use a named mutex, or apply security information. Worse, the issue of choice regarding recursive nature in UNIX is taken away from the user. If the platformstl::process_mutex now mandates recursion the UNIX user may pay unncessary performance costs; if the class mandates non-recursive nature then the class has significantly different behaviour depending on operating system, something that is very wrong and guaranteed to result in platformstl::process_mutex being avoided like the plague.

Rather than attempt either of these absolutist approaches, the principle of Intersecting Conformance dictates that facades for disparate technologies should employ structural conformance only to the degree of the intersection of (meaningfully) identical functionality, rather than employing significant additional functionality to achieve total structural conformance. In other words, where functionality is identical, or very similar, structural conformance is employed to ensure exact syntactic correspondence. Where the functionality is different, such that conformant semantics is not possible, or realisable in an efficient and robust manner, conformance should be explicitly eschewed.

In this way, rich but thin facades may be provided for a given operating system/technology area, while still supporting the construction of higher level components that rely on a common abstracted view of the services provided.