amorph.h File Reference

-*- C++ -*- More...

`#include <iostream>`
`#include <wibble/mixin.h>`
`#include <wibble/cast.h>`
`#include <wibble/maybe.h>`
`#include <wibble/sfinae.h>`
`#include <wibble/test.h>`
Include dependency graph for amorph.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

## Classes

struct | wibble::ReturnType< _T >
struct | wibble::ReturnType< void >
struct | wibble::SanitizeReturn< F, R >
struct | wibble::SanitizeReturn< F, void >
struct | wibble::IsZero< A >
struct | wibble::IsZero< 0 >
struct | wibble::IsPolymorphic< T >
struct | wibble::IsPolymorphic< T >::A
struct | wibble::IsPolymorphic< T >::B
struct | wibble::SanitizeResultType< F >
struct | wibble::Baseless
struct | wibble::VirtualBase
struct | wibble::MorphInterface< Interface >
| An interface implemented by all morph classes. More...
struct | wibble::MorphAllocator
| custom allocator for morph classes More...
struct | wibble::MorphBase< W, Interface >
struct | wibble::Morph< Self, W, Interface >
class | wibble::AmorphPadder< Padding1 >
class | wibble::AmorphPadder< 0 >
struct | wibble::Amorph< Self, _Interface, Padding >
struct | wibble::Amorph< Self, _Interface, Padding >::Convert< T >

## Namespaces

| wibble

## Macros

#define | WIBBLE_AMORPH_H
#define | WIBBLE_AMORPH_PADDING 0
| Amorph base class. More...

## Functions

template<typename T , typename X >
X::template Convert< T >::type & | wibble::downcast (const X &a)

## Detailed Description

-*- C++ -*-

Author
  Peter Rockai me@mo.nosp@m.rnfa.nosp@m.ll.ne.nosp@m.t

## Macro Definition Documentation

#define WIBBLE_AMORPH_H

#define WIBBLE_AMORPH_PADDING 0

Amorph base class.

This class is an Amorph class. An Amorph can hold one of many Morhps of the corresponding kind. That means, Amorph is an envelope that can contain an instance of a Morph. The Amorph envelope can provide methods that all the Morphs that it can hold provide as well. These methods will then act polymoprhically in the Amorph instance, depending on what Morph is inside.

You use the Amorph and Morph classes as values, that is, they have value semantics. You usually do not need (nor want) to use pointers to access them. Of course it may be useful sometimes, but is not the normal mode of operation.

Amorph objects are equal if they hold same type of Morph and the Morphs themselves are also equal. Different types of Morphs are never equal.

When implementing your own Amorph class, you will want it to contain the methods that are shared by all it's Morphs. These will usually look like

methodFoo() { return this->impl()->methodFoo(); }

If you need to dispatch on the type of the Morph inside the Amorph envelope, you can use

if ( amorph.is< MyMorph >() ) { MyMorph morph = amorph; }

or if you write adaptable unary function objects (see stl manual) handling the specific morph types, you can write:

amorph.ifType( functor );

This will call functor on the morph type if the functor's argument_type matches the type of contained Morph. The returned type is Maybe< functor::result_type >. If the type matches, the returned value is Just (returned value), otherwise Nothing.

See wibble::Maybe documentation for details.

This also lends itself to template specialisation approach, where you have a template that handles all Morphs but you need to specialize it for certain Morphs. Eventually, an example of this usage will appear in amorph.cpp over time.

Often, using Amorph types will save you a template parameter you cannot afford. It also supports value-based programming, which means you need to worry about pointers a lot less.

For a complex example of Amorph class set implementation, see range.h.

Implementation details: the current Amorph template takes an integral Padding argument. The MorphImpl class contains an overloaded operator new, that allows it to be constructed off-heap. The Padding argument is used as a number of words to reserve inside the Amorph object itself. If the Morph that will be enveloped in the Amorph fits in this space, it will be allocated there, otherwise on heap. The Padding size defaults to 0 and therefore all Morphs are by default heap-allocated. Reserving a reasonable amount of padding should improve performance a fair bit in some applications (and is worthless in others).